Java abstract static Workaround

前端 未结 15 1925
猫巷女王i
猫巷女王i 2020-12-29 04:43

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?

相关标签:
15条回答
  • 2020-12-29 05:00

    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.

    0 讨论(0)
  • 2020-12-29 05:03

    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.

    0 讨论(0)
  • 2020-12-29 05:04

    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...)

    0 讨论(0)
  • 2020-12-29 05:05

    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.

    0 讨论(0)
  • 2020-12-29 05:10

    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.

    0 讨论(0)
  • 2020-12-29 05:10

    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.

    0 讨论(0)
提交回复
热议问题