"Abstract static" method - how?
Asked Answered
A

11

12

There are already several SO questions on why there is not abstract static method/field as such, but I'm wondering about how one would go about implementing the following psuedo-code:

class Animal {
    abstract static int getNumberOfLegs(); // not possible
}

class Chicken inherits Animal {
    static int getNumberOfLegs() { return 2; }


class Dog inherits Animal {
    static int getNumberOfLegs() { return 4; }

Here is the problem: Assuming that I want make sure that every class that inherits Animal to contain getNumberOfLegs() method (i.e. almost like an interface, except I do want the abstract class to implement several methods that are common to all child classes, hence pure interface does not work here). getNumberOfLegs() obviously should be a static method (assuming that in a perfect world we dont' have crippled chicken and dogs so getNumberOfLegs is not instance-dependent).

Without an "abstract static" method/field, one can either leave the method out from Animal class, then there is the risk that some child class do not have that method. Or one can make getNumberOfLegs an instance method, but then one would have to instantiate a class to find out how many legs that animal has - even though it is not necessary.

How do one usually go about implementing this situation?


EDIT: Here how I might use this. Assume (now this is ridiculous, but anyhow...) that the number of legs of each animal is unique, so I might have something like:

Animal getModelAnimal(int numberOfLegs) {
   if (numberOfLegs == Chicken.getNumberOfLegs()) return new Chicken();
   else if (numberOfLegs == Dog.getNumberOfLegs()) return new Dog();
}
Adieu answered 29/5, 2010 at 23:3 Comment(0)
S
4

How do one usually go about implementing this situation?

The usual solution is to make the method in question an instance method.

getNumberOfLegs() obviously should be a static method (assuming that in a perfect world we dont' have crippled chicken and dogs so getNumberOfLegs is not instance-dependent).

That is emphatically not obvious! We don't program for a perfect world, and in the real world four-legged animals sometimes have one, two, or three (or five) legs.

If your program needs animal definitions rather than animal instances, go ahead and make a class for that.

class AnimalDefinition {
    public string getScientificName();
    public string getCommonName();
    public int    getNumberOfLegs();
    public bool   getIsAmphibious();
    // etc.
}

Then initialize a collection of those at the beginning of your program - ideally from a database or configuration file where you can add animal definitions without writing or compiling another line of code. (And you can get away with far fewer types.)

Shumate answered 30/5, 2010 at 0:11 Comment(0)
N
3

Your pseudocode looked a lot like Java, so I'm going to assume it is Java you are using.

"An abstract method requires implementation per instance. Static methods pertain to an overall class. A static method in an abstract class belongs to the abstract class, not potential implementations. It therefore doesn't make any sense to allow abstract static methods. Furthermore, static methods cannot be overridden, so again, abstract static methods would be an anomaly."

From http://forums.sun.com/thread.jspa?threadID=597378

Please also look at Why can't I define a static method in a Java interface?

Nicker answered 29/5, 2010 at 23:5 Comment(3)
-1: You can't say that generally. abstract method is not always non-sense (see my post).Hamate
Edited my answer to reflect this.Nicker
My question is meant to be language agnostic (I ran into a similar problem in C# before). I can see why there is no "abstract static" modifier in a language, but I'm more interested to see how one can cleanly implement the problem I stated in the question.Adieu
H
3

This is a really good point and sometimes abstract static is really missing. However, as nowadays memory is not a problem, you can surely implement the getNumberLegs()-method as an instance method.

Saying that static abstract is non-sense, is not true. PHP allows abstract static methods (see this) and your scenario shows that it may be useful in some situations.

It's also no true to say that static methods can't be overridden; final methods can't be overridden. In languages like Java and C#, static comes with final. That's why many assume that static equals to "not overrideable".

Talking about C# (after reading your comments, I assume you "speak" C#), you may consider to use generics and attributes (or generics and annotations in Java):

public class Animal
{
   public static int GetNumberOfLegs<T>() where T : Animal
   {
     //Get T's custom attribute "NumberOfLegs" and return its value 
   }

   //EDIT: Added runtime-version of GetNumberOfLegs.
   public static int GetNumberOfLegs(Type t)
   {
     //Get t's custom attribute "NumberOfLegs" and return its value 

   }
}

[NumberOfLegs(4)]
public class Cat { ... };

This will permit you to get the number of legs of each type without instantiating it. Just remember to indicate the [NumberOfLegs(x)] attribute. You also have to know the type at compile time (for the generic version of the method).

EDIT: I added a runtime version of the GetNumberOfLegs()-method, to which you can pass a Type object (should be Class for Java). You will have to make a type check at runtime in this case, i.e. check if the type represented by the Type-/Class-object inherits from Animal and then retrieve the value passed in the attribute/annotation.

Usage:

int numberOfLegs1 = Animal.GetNumberOfLegs<Cat>(); 
int numberOfLegs2 = Animal.GetNumberOfLegs(typeof(Cat)); //runtime version
Hamate answered 29/5, 2010 at 23:12 Comment(3)
It's not a comparison... I'm showing that abstract static is not non-sense. I'm pointing out a general OOP concept.Hamate
sorry, but by itself, Abstract static is still nonsense. You needed a custom attribute to make sense out of this use case.Korella
In languages like Java and C#, static comes with final. That's why many assume that static equals to "not overrideable". (@Simon) -- This is only partially true, at least for Java. Static methods are by default non-final, so a static subclass method with same signature is allowed. A static method in a subclass with the same signature as a static method of a superclass hides the superclass method, but does not override it.Nichollenicholls
V
2

How do one usually go about implementing this situation?

In Java terms, I'd just declare a constructor in the abstract class which takes a fixed argument. Each subclass is then required to invoke it, else it won't compile.

abstract class Animal {
    private int numberOfLegs;

    public Animal(int numberOfLegs) {
        this.numberOfLegs = numberOfLegs;
    }

    public int getNumberOfLegs() {
        return numberOfLegs;
    }
}

class Chicken extends Animal {
    public Chicken() {
        super(2);
    }
}

class Dog extends Animal {
    public Dog() {
        super(4);
    }
}

Update: as per your update

EDIT: Here how I might use this. Assume (now this is ridiculous, but anyhow...) that the number of legs of each animal is unique, so I might have something like:

Animal getModelAnimal(int numberOfLegs) {
   if (numberOfLegs == Chicken.getNumberOfLegs()) return new Chicken();
   else if (numberOfLegs == Dog.getNumberOfLegs()) return new Dog();
}

This is indeed ridiculous, this requires that all of those concrete animals are known beforehand in the abstract factory method. You would need to update the abstract factory method everytime when a new concrete animal type is added. What's the point of the abstract factory then? You already know everything beforehand? No, just let the abstract factory method take the full qualified classname as identifier or so, so that it can try to load from the classpath (still talking in Java terms).

Varitype answered 29/5, 2010 at 23:22 Comment(2)
But getNumberOfLegs() is still an instance method and I have to instantiate the classes to find out how many legs the animal has...Adieu
The getModelAnimal() method is not necessarily defined in the Animal class, though.Adieu
K
0

Even if you could have an abstract static method, how would you use it? Think of how you would use it before you think of how to implement it, as your implementation must match the uses.

Korella answered 29/5, 2010 at 23:7 Comment(0)
T
0

This is an interesting question. In my opinion, "static abstract" methods are rarely needed, and there are always good alternatives.

In the use case you provided, for example, the factory method addresses the concrete animal classes by name; for every new animal class, new specific code should be added. Therefore, it seems like the "abstract" qualification is not really needed. A convention of supplying a static method getNumberLegs() is enough.

And more generally, combining abstract and static has no sense (in Java) since abstract implies polymorphism, while static calls are non-polymorphic at all, and work on classes known at compile time.

Twoply answered 29/5, 2010 at 23:52 Comment(0)
B
0

You could cludge a runtime check that the method is implemented by having your base class throw an exception in its implementation. It isn't worth much, but maybe better'n nothing...

Buttonwood answered 30/5, 2010 at 1:8 Comment(0)
B
0

Abstract methods make sense if you call them in aid of base class. Note that in your example, you aren't utilizing polimorphism at all. In example should be something like:

  (Animal)Dog.getNumberOfLegs() //cast Dog to Animal first

Anyway PHP implements so called "late static binding" which is probably what you are looking for

http://php.net/manual/en/language.oop5.late-static-bindings.php

In C++ similar functionality can be achieved using tamplates and compile-time polymorphism.

Bareilly answered 30/5, 2010 at 1:23 Comment(0)
R
0

abstract static methods only make sense in languages in which variables can contain actual types and not just instances. (Delphi is one such language, c# is not, and I don't think you can do it in Java either). The reason why is that if you know at compile-time exactly which classes you're using (like in your example), then there is no reason for the method to be abstract, you could just have static methods in each class named the same things. The only way in which you could possibly not know what types you're using is if you can assign types to a variable, as then you can pass them around (just like instances of classes) and suddenly everything actually makes sense and is useful.

I think most compilers / languages which support assigning types (as well as instances of types) to variables also manage to support abstract static and virtual abstract methods via compiler magic, so if they're actually useful in your language of choice then they should be supported.

Rheometer answered 30/5, 2010 at 1:39 Comment(4)
Not only languages with variable types. Another case is when such abstract static method is called from other method. Let's say one of the Animal methods calls Animal.getNumberOfLegs(). Then may Dog call in one of its methods this method. Since getNumberOfLegs() is abstract Animal.getNumberOfLegs() inside Animal's method body, might be dispatched to Dog.getNumberOfLegs().Bareilly
That example makes no sense. How is the compiler supposed to know to dispatch a static call to another type based on the signature of the non-static call that you're currently within? That's not how these things work.Rheometer
I think that additionial vtable for static calls should do the job. Anyway, it depends only on RTTI. PHP does something like that (although not exactly).Bareilly
Virtual static methods would make sense in .NET languages; if Foo has a virtual static method Bar, then MakeThing<T>() where T:Foo should be able to use method T.Bar(). Such a thing could be handled with the existing Framework by having T.Bar() translate to Foo.VirtualStaticMethodHolder<T>.Methods.Bar(), and having the compiler generate suitable nested classes in Foo and derivatives; the indicated generic class would use Reflection the first time it was revoked, and a cached reference after that.Woolcott
T
0

one more approach I can see here is to make an abstract factory: this is c# you do not need to make an instance of Chicken to know a number of legs. just invoke the checken factory method

abstract class AnimalFactory
{
    public abstract Animal CreateAnimal();
    public abstract int GetLegs();

}
abstract class Animal
{

}
internal class Chicken : Animal
{

}
class CreateChicken : AnimalFactory
{
    public override Animal CreateAnimal()
    {
        return new Chicken();
    }
    public override int GetLegs()
    {
        return 2;
    }

}
Tindle answered 31/5, 2010 at 14:53 Comment(0)
S
0

For a moment, assume "abstract static methods" are allowed.

Then using your code, I add this :

Animal modelAnimal;
int numLegs;

modelAnimal = this.getModelAnimal(4); // Got a dog

numLegs = modelAnimal.getNumberOfLegs();

I'll get error as modelAnimal which is a Dog object will try to call getNumberOfLegs in Animal class and not Dog class. No overriding for static methods you know. To avoid this situation, designers have not included abstract static methods.

Shimmy answered 20/6, 2011 at 12:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.