28

I understand that neither a abstract class nor an interface can contain a method that is both abstract and static because of ambiguity problems, but is there a workaround?

I want to have either an abstract class or an interface that mandates the inclusion of a static method in all of the classes that extend/implement this class/interface. Is there a way to do this in Java? If not, this may be my final straw with Java...

EDIT 1: The context of this problem is that I have a bunch of classes, call them Stick, Ball, and Toy for now, that have a bunch of entries in a database. I want to create a superclass/interface called Fetchable that requires a static method getFetchables() in each of the classes below it. The reason the methods in Stick, Ball, and Toy have to be static is because they will be talking to a database to retrieve all of the entries in the database for each class.

EDIT 2: To those who say you cannot do this in any language, that is not true. You can certainly do this in Ruby where class methods are inherited. This is not a case of someone not getting OO, this is a case of missing functionality in the Java language. You can try to argue that you should never need to inherit static (class) methods, but that is utterly wrong and I will ignore any answers that make such points.

Community
  • 1
  • 1
twolfe18
  • 2,228
  • 4
  • 24
  • 25
  • The only reason an abstract static method would make any sense is because of Java's weird static method inheritance. C# doesn't let you inherit static methods, because frankly it doesn't make sense to (static methods belong to the class, not the instance). – Powerlord Dec 16 '09 at 16:53
  • 3
    @R. Bemrose: For those of us who are not C# programmers, can you explain how C# is different from Java in terms of the "weird static method inheritance"? Last time I checked Java doesn't support inheritance of static methods. – Asaph Dec 16 '09 at 16:55
  • Can you explain why you need this function which is implemented in all the derived classes to be static? Why is a normal abstract method not sufficient? – Jherico Dec 16 '09 at 17:02
  • As others have mentioned, it makes little sense to do what you are asking. Before you give up on Java, why not let us know how you are trying to model your problem, and see if it can sensibly be done another way? – Mark Bolusmjak Dec 16 '09 at 17:02
  • see my solution, maybe that will explain what I wanted to do. – twolfe18 Dec 16 '09 at 17:08
  • 4
    -1 for stubbornness. As one of the people who disagree with your approach I find it silly of you to exclude my opinion. – Cogsy Dec 17 '09 at 01:14
  • 3
    Regarding your comment on "you can do this in Ruby", I think this just highlights the fact that static methods are not the same as class methods, and Ruby has class methods (so does e.g. Smalltalk and Delphi and Python). Java doesn't have class methods. The difference is that in languages with class methods, class itself is an object, and subclass is also an object of a type derived from the type of its superclass. Thus you have normal inheritance rules for classes, with virtual dispatch, overrides etc. Java doesn't have that, hence no static overrides, hence no `static abstract`. – Pavel Minaev Dec 17 '09 at 01:31
  • 1
    -1 for down-voting answers to your own question. It is bad manners to down-vote people who have made the effort to answer ... even if they've got it totally wrong. – Stephen C Dec 17 '09 at 04:41
  • As to your example, I can see why I've never run into this. It's sometimes really convenient to lump data retrieval right into the data class but I've had too many cases where today I need to retrieve my Balls from a DB, tomorrow an XML file, and the next day an LDAP server. Having a separate object hierarchy (with interfaces) for the data access makes this easier at the "cost" of keeping the data classes clean. – PSpeed Dec 17 '09 at 07:52
  • "The reason the methods in Stick, Ball, and Toy have to be static is because they will be talking to a database to retrieve all of the entries in the database for each class." And why does this mean they MUST be static? Instance methods can very obviously do this. Do you actually just want singletons? – GaryF Dec 17 '09 at 09:07
  • 3
    @GaryF - all i mean is that it is bad practice to have a non-static method that does things that have nothing to do with an instance of the class (fetching all records from the DB has nothing to do with individual instances => static). – twolfe18 Dec 17 '09 at 22:39
  • 1
    @twolfe18 but it is related to a specific class instance: your DB access class. – Cogsy Dec 17 '09 at 23:10
  • "The reason the methods in Stick, Ball, and Toy have to be static is because they will be talking to a database to retrieve all of the entries in the database for each class." This seems to break the separation of concerns rule. I would expect that the database persistence layer would know how to fetch a polymorphic list of Toys. But why would a Toy need to know how it is stored in the database? Standard tools like iBatis and Hibernate will implement this for you. – kiwiron Mar 23 '15 at 07:24

15 Answers15

8

There are lots of answers about 'this does'nt make sense..' but indeed I met a similar problem just yesterday.

I wanted to use inheritance with my unit tests. I have an API and several its implementations. So I need only 1 set of unit tests for all implementations but with different setUp methods which are static.

Workaround: all tests are abstract classes, with some static fields with protected access modifier. In all implementations I added static methods which set these static fields. It works rather nice, and I avoided copy and paste.

Roman
  • 64,384
  • 92
  • 238
  • 332
  • 2
    this is pretty much equivalent to what I am going to do, with some tweaks. I need to worry about the return type for the static methods though. – twolfe18 Dec 16 '09 at 17:22
8

You have a couple of options:

  1. Use reflection to see if the method exists and then call it.
  2. Create an annotation for the static method named something like @GetAllWidgetsMethod.

  3. As others have said, try to not use a static method.

Dave
  • 13,518
  • 7
  • 42
  • 51
  • Basically, you could look at the class's static methods and see if one has the annotation and then call it. Neither option 1 or 2 provide a way of enforcing that at compile time, however. – Dave Dec 16 '09 at 18:50
5

I too am dealing with this problem. For those that insist that it "doesn't make sense", I would invite you to think outside of that semantic box for a moment. The program I am working with is inherently about reflection.

Reflection, as you know, can take three orders of magnitude longer than straight-up binary function calling. That is an inevitable problem, and the software needs to port to as many machines as possible, some of which will be 32 bit and slower than my development machine to begin with. Thus, the applicability of a class to the requested operation needs to be checked via a static method, and all of the reflective methods are run at once during module booting.

Everything works, first and foremost. I've built the entire thing. The only catch is that a module can be compiled in a .class without compile time checking to see if the identifying static function exists at all, resulting in an innately useless class. Without the identifier, and its included information, for security's sake the module is not loaded.

I clearly understand the issue with the complete definition of "abstract" and "static", and understand that they don't make sense together. However, the ability to have a class method that is compiler-enforced for inclusion is lacking in Java, and as much as I like the language, I miss it. Thus, this is a human constraint on every programmer that ever works on the software, which I'm sure we can all agree is a pain.

2

There's a lot of 'this makes no sense' or 'this can't be because' and 'why do you want it?' (or worse: 'you don't have to want it!') in all those answers. However, these answers also indirectly give reasons why it should be possible.

It must be differentiated between the concept and the implementation. Sure, overriding a static method makes no sense. And it also isn't what the question was about.

It was asked for a way to force implementation of a certain static method (or constant or whatever) in every derived class of an abstract class. Why this is required it the matter of the one who wants to write an appllication with Jave, and no business of anyone else.

This has nothing to do with how the compiler compiles the method and how it is done at runtime.

Why shoudl it be possible? because there are things that are class specific (and not instance specific) and therefore should be static, while they NEED to be impleented in every single subclass (or class that implements an interface).

Let's say there is an abstract class 'Being'. Now there are subclasses like 'animals' and 'plants'. Now there are only mammals and fishes allowed for animals. This information is specific to the animals class, not to any instance nor doe sit belong to any superclass or subclass. However, this information must be provided by teh class, not an instance, because it is required to properly construct an animal instance. So it MUST be there and it CANNOT be in the instance.

In fact, Java has such a thing- Every object has a class specific field 'class'. It is class-specific, not inherited, no override and it must be there. Well the compiler creates it implicitly, but obviously the compiler CAN do it. So why not allowing this for own fields too. After all, it is just a matter of definition how the combination 'abstract static' is interpreted when the compiler checks the intheritance chain for abstract functions. Nobody was ever demanding that there should be an inheritance of the superclass class functions (which could still make some sense, depending on what this function actually does - after all classes inherit static functions of their superclasses, even though you might get a warning that you should access it directly when you call it by the subclass))

But to summarize: the Java language offers no way to do it at compile time while there is no reason (othe rthan plain dogmatic) to not doing so. The only way is to write a static final function to the abstract class that tries to find the static function/field of the subclass when it is loaded (or loads all existing subclasses and checks them). If properly made, it gives a runtime error on first use. Complex and dirty but better than nothing. At least it prevents bugs where you get the information from the wrong superclass. It won't work for interfaces, though.

1

A type system allows you to express some constraints among types, but it's limited. That's why javadocs are littered with constraints in human language, asking people to follow rules that the compiler cannot check.

if you want to extend it beyond what language provides natively, you can write your own static analysis tool. that is not uncommon. for example: findbug. also IDEs do that too, they checking thing beyond what language dictates. you can write a plug in to enforce that a subclass must have a static method of such signature.

in your case, it's not worth it. have javadoc in the superclass urge implementors to include a static method, that's good enough.

I'll provide a convoluted way of expressing your constraint anyway, but DO NO DO IT. people get really carried away of make everything checkable at compile time, at the price of making code unreadable.

interface WidgetEnumerator
{
    List getAllWidgets();
}

public class Abs<T extends WidgetEnumerator>
{
    static List getAllWidgets(Class<? extends Abs> clazz){ ... }
}

public class Sub extends Abs<SubWidgetEnumerator>
{
}

public class SubWidgetEnumerator implements WidgetEnumerator
{
    public List getAllWidgets() { ... }
}

How it works: for any subclass of Abs, it is forced to provide an implementation of WidgetEnumerator. subclass author cannot forget that. Now invocation Abs.getAllWidgets(Sub.class) contains sufficient information to resolve that implementation, i.e. SubWidgetEnumerator. It is done through reflection, but it is type safe, there are no string literals involved.

irreputable
  • 44,725
  • 9
  • 65
  • 93
1

I think I can give you a better answer after seeing your edits--your best bet is probably a factory pattern. (Not lovely, but better than singleton).

abstract class Widget
    public static Widget[] getAllWidgetsOfType(Class widgetType) {
        if(widgetType instanceof ...)
    }
class Ball extends Widget
class Stick extends Widget
class Toy extends Widget

This is not a very good way to do it, but it's typical. Hibernate is the tool you would normally use to solve this problem, this is exactly what it's designed for.

The big problem is that it requires editing the base class whenever you add a new class of a given type. This can't be gotten around without reflection. If you want to use reflection, then you can implement it this way (Psuedocode, I'm not going to look up the exact syntax for the reflection, but it's not much more complex than this):

public static Widget[] getAllWidgetsOfType(Class widgetType) {
    Method staticMethod=widgetType.getStaticMethod("getAllInstances");
    return staticMethod.invoke();
}

This would give the solution you were asking for (to be bothered by the need to modify the base class each time you add a child class is a good instinct).

You could also make it an instance method instead of a static. It's not necessary, but you could then prototype the method (abstract) in Widget.

Again, all this is unnecessary and sloppy compared to Hibernate...

Edit: If you passed in a live "Empty" instance of a ball, stick or toy instead of it's "Class" object, you could then just call an inherited method and not use reflection at all. This would also work but you have to expand the definition of a Widget to include an "Empty" instance used as a key.

Bill K
  • 62,186
  • 18
  • 105
  • 157
1

Static methods are relevant to an entire class of object, not the individual instances. Allowing a static method to be overridden breaks this dictum.

The first thing I would consider is to access your database from a non-static context. This is actually the norm for Java apps.

If you absolutely must use a static method, then have it parameterised with instance specific arguments (of a generic type) to allow the different subclasses to interact with it. Then call that single static method from you polymorphic methods.

Cogsy
  • 5,584
  • 4
  • 35
  • 47
  • "abstract" is not overriding, but enforcing that an implementation is provided. – foo Feb 18 '21 at 11:34
0

No. You can't do that. If you're willing to compromise and make the method non-static or provide an implementation of the static method in your abstract class, you'll be able to code this in Java.

Asaph
  • 159,146
  • 25
  • 197
  • 199
0

Is there a way to do this in Java?

I don't think there is a way to do this in any language. There's no point to it, since static methods belong to a class and can't be called polymorphically. And enabling polymorphic calls is the only reason for interfaces and abstract classes to exist.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • 2
    so in each of the subclasses i just need to write a static method getAllWidgets, there's no way to indicate programmatically that that method exists? – twolfe18 Dec 16 '09 at 17:02
  • How would you call it? besides, there's probably a better solution: have that method fully implemented in a base class, taking a Class object as parameter - the base class constructor can take cake or registering all instances. – Michael Borgwardt Dec 16 '09 at 17:10
  • 1
    @Michael what you describes is similar to what I ended up doing. but to your first question, say class A extended this abstract class which required abstract static getBlahBlah(), you would call it like A.getBlahBlah(). I don't really see why people are taking this so poorly, I don't think I'm asking something unreasonable. – twolfe18 Dec 16 '09 at 17:13
  • @Michael, also, I know that in my previous comment that you can't have an abstract static class, and that if you called (A's super class).getBlahBlah() there would be a ambiguity problem, but my original question was about a workaround to this problem. – twolfe18 Dec 16 '09 at 17:15
  • The thing is: interfaces and abstract classes are part of the language's formal type system. The methods you need aren't - they're a convention for the convenience of the programmer. – Michael Borgwardt Dec 16 '09 at 17:20
  • @Michael I see your point, but I don't believe the language's design (type system or otherwise) should be limiting or more important that what the programmer wants to do (provided the programmer isn't an idiot... which I don't think I am...). I guess its just a philosophical difference between me and the people who wrote Java. I think this is a case of poor design in Java, but maybe I'm just getting too comfortable with duck-typed languages. – twolfe18 Dec 16 '09 at 17:26
  • Java isn't limiting here - quite the opposite: it doesn't enable *you* to force programmers using your class / implementing your interface to follow your convention. How would you do the thing you're after in a duck-typed language? Don't those provide even fewer ways to do things like that? – Michael Borgwardt Dec 16 '09 at 17:35
  • @Michael - Java is limiting: by my book, my will trumps Java's ideas about what I should and shouldn't force other programmers to do. I may have mis-spoke about the solution being easier in a duck-typed language. What I meant is that in a language like Ruby, a class is an object, so it makes sense to inherit static methods. This means that I could at least do what I want to do (if Ruby had interfaces/abstract classes...), but I might get a NotImplementedError. Still ugly. I'm sure there is a language out there that has an elegant way to do what I want to do! – twolfe18 Dec 16 '09 at 17:55
  • @twolfe18 - "I'm sure there is a language out there that has an elegant way to do what I want to do!" Well stop complaining about Java, and start looking for that language. :-) – Stephen C Dec 17 '09 at 04:33
  • @Stephen, this language is Object Pascal (or Delphi if you prefer) and this way is called "virtual class methods", see http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/classmethods_xml.html#code00526 – mschayna Mar 23 '10 at 14:09
  • @mschayna - tell it to @twolfe18 ... I'm not the one complaining about Java :-) – Stephen C Mar 23 '10 at 14:26
  • @mschayna - and in a Delphi program in the field I have seen EAbstractError, more than once, and it's not pretty when your customers see it. Java is trying to help you design better. – Chad N B Aug 29 '13 at 04:02
  • 3
    Python, among others, does exactly this with its class methods, it's not an inherit limitation of all languages, just of Java. – Eloff Apr 28 '14 at 13:26
0

Create a context interface containing your method with a name that matches your problem domain. (Name it "World" if you absolutely have to, but most of the time there's a better name)

Pass around implementation instances of the context object.

fforw
  • 5,391
  • 1
  • 18
  • 17
  • kind of ugly, but it could work. i probably wouldn't use this though because its uglier than my current solution which is to just have a version of that static method in each of my subclasses. – twolfe18 Dec 16 '09 at 17:18
0

Ok, maybe my question was poorly asked, it seems like most of you didn't get what I was trying to do. Nonetheless, I have a solution that is somewhat satisfactory.

In the abstract super class, I am going to have a static method getAllWidgets(Class type). In it I'll check the class you passed it and do the correct fetching based on that. Generally I like to avoid passing around classes and using switches on stuff like this, but I'll make an exception here.

twolfe18
  • 2,228
  • 4
  • 24
  • 25
  • 2
    It's a very common case of badly-asked question: you had already decided on an (unworkable) solution to your actual problem and then asked how to get that solution to work without mentioning your actual motivation. BTW, you shouldn't have to use a switch here, a Map> should do the trick. Should even be possible to use a generic type parameter so that the method becomes typesafe. – Michael Borgwardt Dec 16 '09 at 17:24
  • 1
    You don't really seem to get OO (as most answers here have pointed out). I'll give you one hint, if you are relying on static methods for more than trivial functions, you're doing it wrong. If you posted more of your problem we might be able to help you but as with most programming problems, it's hard to solve correctly without a much bigger picture. I would suggest you redo your design with no statics at all to break yourself of the habit for starters. I wish there was an easy way to share UML style design diagrams--seeing yours might help too. – Bill K Dec 16 '09 at 17:55
  • @Michael - your recommendations about the map and the type parameter are noted, good points. I did not however have this solution planned when I asked the question. – twolfe18 Dec 16 '09 at 18:08
  • @Bill - Frankly I don't appreciate you telling me I don't understand OO. I am working on an application that is requires dealing with collections of objects a lot, so methods like getAllWidgets are needed (I consider them trivial), and they need to be static. Maybe you should spend less time on SO and more time with a framework like Rails to get a better idea of how OO can be applied more broadly. – twolfe18 Dec 16 '09 at 18:09
  • 1
    @twolfe: your "trivial" methods aren't trivial, because of the problems you're running into here. If you need polymorphism, they cannot (and should not) be static methods. – Andrzej Doyle Dec 16 '09 at 18:27
  • 1
    @Andrzej - 1. the methods are trivial, working them into Java seems not so trivial. 2. do you really think that a method that fetches a bunch of objects irrespective of the context should not be static? 3. what is wrong with inheritance of static methods? it seems like everyone here is arguing: "Java doesn't let you do it, so it must be wrong!" Anyone have any real reasons why you shouldn't have polymorphism and static methods together? – twolfe18 Dec 16 '09 at 18:41
  • @twolfe18 I've spent a year working on rails, 10 years programming in OO, and 20 years programming altogether. (I do like Active Record, BUT it's not perfect). You shouldn't be passing around naked collections at all, you should be passing around business objects. Does your class diagram actually have a bunch of collections in it? If you didn't bristle and actually tried what I suggested (avoiding static methods) you might learn something sooner than later--but if you want to learn your own way, enjoy (most of us learned by doing it wrong the first time--nothing wrong with that!) – Bill K Dec 16 '09 at 18:51
  • @Bill - how do you propose I do this without static methods? the only way I can think of is to create a singleton called WidgetCollection. singletons are still just a OO workaround for static methods (I think singletons are not very OO at all -- still valuable though). but two more things: 1. I don't necessarily think that OO is the second coming of Christ, there is more than one way to write an elegant program. 2. if you're not proposing I use singletons, do you care to explain how you would do it? – twolfe18 Dec 16 '09 at 18:59
  • I think until an actual example of what you are really doing (and not just interfaces) is provided then this argument will continue to go around in circles. There is a disconnect here somewhere and the "crowd" is not properly equipped to bridge the gap. Maybe you can edit your question with a more concrete use-case? – PSpeed Dec 16 '09 at 20:06
  • @Bill, if you have worked with rails, you must see the similarity between what I want to do and ActiveRecord's find method? find is a static method that is inherited by all methods that extend ActiveRecord::Base, thats what I want to do in Java. – twolfe18 Dec 16 '09 at 21:21
  • 1
    @twolfe18 You seem to need different WidgetCollections instances, not a singleton (otherwise you wouldn't be asking about different static methods)--but as I said, I don't have a big enough picture to feel sure about that. Also a "WidgetCollection" sounds generic, not really like a business class. Usually such an object is attached to or created from another object, so you rarely need things like static factory methods either (usually these are another indication that your OO could be better). I understand not liking OO, but if you're going to do it then don't go at it half assed. – Bill K Dec 16 '09 at 23:04
  • I understand what you are saying, but Ruby is a very different language from Java. You can't implement AR in java--and I wouldn't even suggest trying. The big difference is that Ruby can bind your data with your code on it's own (This is why I was impressed with AR I've tried to do it in Java and it's HARD). You might look into Hibernate for our best approximation. – Bill K Dec 16 '09 at 23:07
0

static methods can't be abstract because they aren't virtual. Therefore anywhere that calls them has to have the concrete type with the implementation. If you want to enforce that all implementations of an interface have a certain static method, then that suggests a unit test is required.

abstract class A
{
    public static void foo()
    {
        java.lang.System.out.println("A::foo");
    }

    public void bar()
    {

        java.lang.System.out.println("A::bar");
    }
}

class B extends A
{
    public static void foo()
    {
        java.lang.System.out.println("B::foo");
    }

    public void bar()
    {

        java.lang.System.out.println("B::bar");
    }
}

public class Main
{
    public static void main(String[] args)
    {
        B b = new B();
        b.foo();
        b.bar();

        A a = b;
        a.foo();
        a.bar();
    }
}
Douglas Leeder
  • 52,368
  • 9
  • 94
  • 137
0

For what it is worth I know exactly what you are trying to do.

I found this article while searching for the reasons I can't do it either.

In my case I have HUNDREDS of classes that inherit from a central base base and I want simply to get a reference like this:

ValueImSearchingFor visf = StaticClass.someArbitraryValue()

I do NOT want to write/maintain someArbitraryValue() for each and every one of hundreds of the inherited classes -- I just want to write logic once and have it calc a Unique Class-Sepcific value for each and every future written class WITHOUT touching the base class.

Yes I completely get OO - I've been writing Java for about as long as it's been available.

These specific classes are more like "Definitions" as opposed to actual Objects and I don't want to instantiate one every time I just need to see what someArbitraryValue() actually is.

Think of it as a PUBLIC STATIC FINAL that allows you to run a Method ONCE to set it initially. (Kinda like you can do when you define an Enum actually...)

Techmag
  • 1,383
  • 13
  • 24
-1

I'd make a WidgetCollection class with an abstract Widget inner class.

You can extend the WidgetCollection.Widget class for each of your types of Widget.

No static methods necessary.

Example (not compiled or tested):

class WidgetCollection<W extends Widget> {
    Set<W> widgets = new HashSet<W>();

    Set<W> getAll() {
        return widgets;
    }

    abstract class Widget {

       Widget() {
           widgets.add(this);
       }

       abstract String getName();
    }

    public static void main(String[] args) {
         WidgetCollection<AWidget> aWidgets = new WidgetCollection<AWidget>();
         a.new AWidget();

         Set<AWidget> widgets = aWidgets.getAll();
    }
}

class AWidget extends Widget {
    String getName() {
        return "AWidget";
    }
}
Skip Head
  • 7,580
  • 1
  • 30
  • 34
-2

It doesn't make sense to do what you're asking:

Why can't static methods be abstract in Java

Community
  • 1
  • 1
GaryF
  • 23,950
  • 10
  • 60
  • 73
  • how does it not make sense to do what i'm asking. if you had a couple classes that all needed a static method getAllWidgets (where widget is the superclass or interface), why is it unreasonable to want to require a static method (in each of the subclasses) getAllWidgets that returns a collection of instances of the subclass/class that implements the interface? – twolfe18 Dec 16 '09 at 17:01