13

There are numerous questions about the impossibility of including static abstract Java methods. There are also quite a lot about workarounds for this (design flaw/design strength). But I can't find any for the specific problem I'm going to state shortly.

It seems to me that the people who made Java, and quite a lot of the people who use it, don't think of static methods the way I, and many others, do - as class functions, or methods that belong to the class and not to any object. So is there some other way of implementing a class function?

Here is my example: in mathematics, a group is a set of objects that can be composed with each other using some operation * in some sensible way - for example, the positive real numbers form a group under normal multiplication (x * y = x × y), and the set of integers form a group, where the 'multiplication' operation is is addition (m * n = m + n).

A natural way to model this in Java is to define an interface (or an abstract class) for groups:

public interface GroupElement
{
  /**
  /* Composes with a new group element.
  /* @param elementToComposeWith - the new group element to compose with.
  /* @return The composition of the two elements.
   */
  public GroupElement compose(GroupElement elementToComposeWith)
}

We can implement this interface for the two examples I gave above:

public class PosReal implements GroupElement
{
  private double value;

  // getter and setter for this field

  public PosReal(double value)
  {
    setValue(value);
  }

  @Override
  public PosReal compose(PosReal multiplier)
  {
    return new PosReal(value * multiplier.getValue());
  }
}

and

public class GInteger implements GroupElement
{
  private int value;

  // getter and setter for this field

  public GInteger(double value)
  {
    setValue(value);
  }

  @Override
  public GInteger compose(GInteger addend)
  {
    return new GInteger(value + addend.getValue());
  }
}

However, there's one other important property that a group has: every group has an identity element - an element e such that x * e = x for all x in the group. For example, the identity element for positive reals under multiplication is 1, and the identity element for integers under addition is 0. In that case, it makes sense to have a method for each implementing class like the following:

public PosReal getIdentity()
{
  return new PosReal(1);
}

public GInteger getIdentity()
{
  return new GInteger(0);
}

But here we run into problems - the method getIdentity doesn't depend on any instance of the object, and should therefore be declared static (indeed, we may wish to refer to it from a static context). But if we put the getIdentity method into the interface then we can't declare it static in the interface, so it can't be static in any implementing class.

Is there any way of implementing this getIdentity method that:

  1. Forces consistency over all implementations of GroupElement, so that every implementation of GroupElement is forced to include a getIdentity function.
  2. Behaves statically; i.e., we can get the identity element for a given implementation of GroupElement without instantiating an object for that implementation.

Condition (1) is essentially saying 'is abstract' and condition (2) is saying 'is static', and I know that static and abstract are incompatible in Java. So are there some related concepts in the language that can be used to do this?

John Gowers
  • 2,646
  • 2
  • 24
  • 37
  • `static` methods are not inherited... – Luiggi Mendoza Mar 17 '14 at 15:45
  • @LuiggiMendoza Yes... – John Gowers Mar 17 '14 at 15:46
  • So, why not to move this method to a Factory instead? – Luiggi Mendoza Mar 17 '14 at 15:47
  • 1
    What's the idea behind it? `static` means it does not depend of the specific instance - but on the static type, and `abstract` means you want the dynamic type to be called. This is self contradicting. If you find yourself in a need for something so bizzare - it is a definite [code smell](http://en.wikipedia.org/wiki/Code_smell). – amit Mar 17 '14 at 15:48
  • `static` methods are inherited, any method that is declared as `public` or `protected` can be seen by a child class.. – Tristan Mar 17 '14 at 15:48
  • 1
    Do you have objects for the operations? it would seem like that would be where the identity would belong, as part of the operation instance. no static required. – Nathan Hughes Mar 17 '14 at 15:50
  • @Tristan read my first comment... – Luiggi Mendoza Mar 17 '14 at 15:50
  • I think the main idea here is that he wants to find a way to get the compiler to *require* that any subclass define this static method. Seems reasonable. However, any static method would have to be called via `Class.getIdentity()`, and if some other client tries to call it and it doesn't exist, it's still a compile-time error, even though it occurs later than the OP would like. But it's still better than an error that doesn't occur until run time. – ajb Mar 17 '14 at 15:52
  • 2
    @LuiggiMendoza I did read it, but it's not correct. `static` methods are inherited just like any other method. http://stackoverflow.com/questions/10291949/are-static-methods-inherited-in-java – Tristan Mar 17 '14 at 15:53
  • You could define your interface as an abstract class and provide a static implementation of getIdentity, so that all the children of the abstract class may invoke the getIdentity method as static. Am I missing something? – Karura91 Mar 17 '14 at 15:55
  • @NathanHughes - A group essentially *is* just an operation - if I relabelled the integers by the letters of the alphabet but kept the operation, it would be the same group. All the information about the group is kept in the particular implementation of the `GroupElement` interface, including the operation itself. But the identity depends on the group itself (the class), rather than on individual group elements (instances of the class), so it should be static. – John Gowers Mar 17 '14 at 15:56
  • @Donkey_2009 Did I understand the problem correctly, or do you need a way to call `getIdentity` where the actual class isn't known at compile time? – ajb Mar 17 '14 at 15:56
  • 1
    @ajb I do want a way to call `getIdentity` when you don't know the actual class at compile time. – John Gowers Mar 17 '14 at 15:57
  • Please give an example of how you expect to refer to `getIdentity` in a static context – Nick Holt Mar 17 '14 at 16:03
  • @NickHolt I might, for example, want to write another class that takes a group as a generic type parameter. It would then make sense for me to have access to the identity element in the group. But if the `getIdentity` method is not static, then I have to create an instance of the group (which would require me to pass in a `.class` parameter and make the code a lot less readable). – John Gowers Mar 18 '14 at 17:30
  • @NickHolt - sorry, forget that; that's impossible even if the method is declared as `static`. – John Gowers Mar 18 '14 at 17:42

7 Answers7

5

Essentially what you are asking for is the ability to enforce, at compile time, that a class defines a given static method with a specific signature.

You cannot really do this in Java, but the question is: Do you really need to?

So let's say you take your current option of implementing a static getIdentity() in each of your subclasses. Consider that you won't actually need this method until you use it and, of course, if you attempt to use it but it isn't defined, you will get a compiler error reminding you to define it.

If you define it but the signature is not "correct", and you attempt to use it differently than you have defined it, you will also already get a compiler error (about calling it with invalid parameters, or a return type issue, etc.).

Since you can't call subclassed static methods through a base type, you're always going to have to call them explicitly, e.g. GInteger.getIdentity(). And since the compiler will already complain if you try and call GInteger.getIdentity() when getIdentity() isn't defined, or if you use it incorrectly, you essentially gain compile-time checking. The only thing you're missing, of course, is the ability to enforce that the static method is defined even if you never use it in your code.

So what you have already is pretty close.

Your example is a good example that explains what you want, but I would challenge you to come up with an example where having a compile-time warning about a missing static function is a necessity; the only thing I can think of that sort of comes close is if you are creating a library for use by others and you want to ensure that you don't forget to implement a particular static function -- but proper unit testing of all your subclasses can catch that during compile-time as well (you couldn't test a getIdentity() if it wasn't present).

Note: Looking at your new question comment: If you are asking for the ability to call a static method given a Class<?>, you cannot, per se (without reflection) -- but you can still get the functionality you want, as described in Giovanni Botta's answer; you will sacrifice compile-time checks for runtime-checks but gain the ability to write generic algorithms using identity. So, it really depends on your end goal.

Community
  • 1
  • 1
Jason C
  • 38,729
  • 14
  • 126
  • 182
  • I think I came up with a great scenario of how `static abstract` would be very useful. In fact, I'm currently trying to solve a problem and `static abstract` would make it much simpler. Here's the question that illustrates it: http://stackoverflow.com/questions/33326553/how-do-you-design-one-screen-to-handle-many-similar-subclassed-objects – ryvantage Oct 25 '15 at 05:34
  • 2
    Basically, I have four database tables that can all be represented by one superclass object, but the database tables have different tablenames/columnames. The tablename is really a property of the _class_, not of the _instance_. So, it would be awesome if the supertype could force the subtype to define a static variable that the superclass can then use in a static context. A static, abstract variable. – ryvantage Oct 25 '15 at 05:37
  • Couldn't you argue the same way about non-static methods? It seems what you're suggesting is to disregard the purpose of having interfaces/abstract classes in the first place, which doesn't really help. – Sambo May 14 '18 at 12:47
3

A mathematical group only has one characteristic operation, however a Java class can have any number of operations. Therefore these two concepts don't match.

I can imagine something like a Java class Group consisting of a Set of elements and a specific operation, which would be an interface by itself. Something like

public interface Operation<E> {
   public E apply(E left, E right);
}

With that, you can build your group:

public abstract class Group<E, O extends Operation<E>> {
    public abstract E getIdentityElement();
}

I know this is not entirely what you had in mind, but as I stated above, a mathematical group is a somewhat different concept than a class.

Ray
  • 3,084
  • 2
  • 19
  • 27
3

There may be some misunderstaning in your reasoning. You see a mathematical "Group" is as you define it (if I can remember well); but its elements are not characterized by the fact that they belong to this group. What I mean is that an integer (or real) is a standalone entity, that also belongs to Group XXX (among its other properties).

So, in the context of programming, I would separate the definition (class) of a Group form that of its members, probably using generics:

interface Group<T> {
    T getIdentity();
    T compose(T, T);
}

Even more analytic definition would be:

/** T1: left operand type, T2: right ..., R: result type */
interface BinaryOperator<T1, T2, R> {
    R operate(T1 a, T2 b);
}

/** BinaryOperator<T,T,T> is a function TxT -> T */
interface Group<T, BinaryOperator<T,T,T>> {
    void setOperator(BinaryOperator<T,T,T> op);
    BinaryOperator<T,T,T> getOperator();
    T getIdentity();
    T compose(T, T); // uses the operator
}

All that is an idea; I haven't actually touched math for a long time, so I could be wildly wrong.

Have fun!

Nikos Paraskevopoulos
  • 39,514
  • 12
  • 85
  • 90
  • I agree. The modeling must be done at the group level, not group element level. That'll solve a lot of problems and make for a more appropriate object oriented model. – Giovanni Botta Mar 17 '14 at 16:07
2

There is no java way of doing this (you might be able to do something like that in Scala) and all the workarounds you will find are based on some coding convention.

The typical way in which this is done in Java is to have your interface GroupElement declare two static methods such as this:

public static <T extends GroupElement> 
  T identity(Class<T> type){ /* implementation omitted */ }

static <T extends GroupElement> 
  void registerIdentity(Class<T> type, T identity){ /* implementation omitted */ }

You can easily implement those methods by using a class to instance map or a home grown solution of choice. The point is you keep a static map of identity elements, one per each GroupElement implementation.

And here comes the need for a convention: each subclass of GroupElement will have to statically declare its own identity element, e.g.,

public class SomeGroupElement implements GroupElement{
  static{
    GroupElement.registerIdentity(SomeGroupElement.class, 
      /* create the identity here */);
  }
}

In the identity method you can throw a RuntimeException if the identity was never registered. This won't give you static checking but at least runtime checking for your GroupElement classes.

The alternative to this is a little more verbose and requires you to instantiate your GroupElement classes through a factory only, which will also take care of returning the identity element (and other similar objects/functions):

public interface GroupElementFactory<T extends GroupElement>{
  T instance();
  T identity();
}

This is a pattern typically used in enterprise applications when the factory is injected through some dependency injection framework (Guice, Spring) in the application and it might be too verbose, harder to maintain and maybe overkill for you.

EDIT: After reading some of the other answers, I agree that you should model at the group level, not the group element level, since element types could be shared between different groups. Nonetheless, the above answers provides a general pattern to enforce the behavior you describe.

EDIT 2: By "coding convention" above, I mean having a static method getIdentity in each subclass of GroupElement, as mentioned by some. This approach has the down side of not allowing generic algorithms to be written against the group. Once again, the best solution to that is the one mentioned in the first edit.

Giovanni Botta
  • 9,626
  • 5
  • 51
  • 94
  • This poses essentially the same problem that the OP posed, just in a different form. Where the OP wanted to enforce that a particular static method was defined, this solution still requires a particular static initialization step to be done, and that step also isn't enforced. One way or another, some static thing must be done that the compiler doesn't enforce. In the OP's particular situation, one additional issue with this solution is that errors aren't caught until runtime. – Jason C Mar 17 '14 at 16:03
  • Any solution will have this downside in Java as I point out at the beginning of my answer. There is no way to statically enforce this behavior, so it has to be enforced through a runtime check. – Giovanni Botta Mar 17 '14 at 16:05
  • You can get *close* to compile-time checks though. Consider: `GInteger.getIdentity()` will fail at compile time if the identity (`getIdentity()`) isn't defined. – Jason C Mar 17 '14 at 16:07
  • 1
    That's just a convention though and doesn't allow you to write generic algorithms on the group, while my solution does. However, as I mentioned at the end of my answer, the best solution is to change approach entirely and model the group instead of its elements. – Giovanni Botta Mar 17 '14 at 16:09
  • As @NikosParaskevopoulos mentions. – Giovanni Botta Mar 17 '14 at 16:10
  • Yes I agree with that. I am not sure if the OP is asking about a general case and using mathematical groups as an example, or is asking specifically about his implementation of groups. – Jason C Mar 17 '14 at 16:11
  • One nice thing about this solution, by the way, is that it lets you grab an identity without knowing the type if you have an object of that type at hand, e.g. `GroupElement.identity(myElement.getClass())`. – Jason C Mar 17 '14 at 16:14
  • 1
    That's what I meant when I said generic algorithms for the group: in order to get the identity you don't need to know the type beforehand, thus you can write a generic algo for any group. – Giovanni Botta Mar 17 '14 at 16:15
  • I try to implement this solution and I have error for T identity(Class type){ /* implementation omitted */ } - missing return statement. How I can solve it? – Beacze Oct 27 '17 at 15:24
  • How could look possibly implementation of getInstance method? – Beacze Oct 27 '17 at 15:54
1

If you need the ability to generate an identity where the class isn't known at compile time, the first question is, how do you know, at run time, what class you want? If the class is based on some other object, then I think the cleanest way is to define a method in the superclass that means "get an identity whose class is the same as" some other object.

public GroupElement getIdentitySameClass();

That would have to be overridden in each subclass. The override would probably not use the object; the object would be used only to select the correct getIdentity to call polymorphically. Most likely, you'd also want a static getIdentity in each class (but there's no way I know of for the compiler to force one to be written), so the code in the subclass would probably look like

public static GInteger getIdentity() { ... whatever }

@Override
public GInteger getIdentitySameClass() { return getIdentity(); }

On the other hand, if the class you need comes from a Class<T> object, I think you'll need to use reflection starting with getMethod. Or see Giovanni's answer, which I think is better.

ajb
  • 31,309
  • 3
  • 58
  • 84
1

We all agree, if you want to implement groups you are going to need a group interface and classes.

public interface Group<MyGroupElement extends GroupElement>{
    public MyGroupElement getIdentity()
}

We implement the groups as singletons so we can access getIdentity statically through instance.

public class GIntegerGroup implements Group<GInteger>{

    // singleton stuff
    public final static instance = new GIntgerGroup();
    private GIntgerGroup(){};

    public GInteger getIdentity(){
        return new GInteger(0);
    }
}

public class PosRealGroup implements Group<PosReal>{

    // singleton stuff
    public final static instance = new PosRealGroup();
    private PosRealGroup(){}        

    public PosReal getIdentity(){
        return new PosReal(1);
    }
}

if we also need to be able to get the identity from a group element, I would update your GroupElement interface with:

public Group<GroupElement> getGroup();

and GInteger with:

public GIntegerGroup getGroup(){
    return GIntegerGroup.getInstance(); 
}

and PosReal with:

public PosRealGroup getGroup(){
    return PosRealGroup.getInstance(); 
}
Colin
  • 588
  • 6
  • 9
0

" the method getIdentity doesn't dependonany instance of the object, and should therefore be declared static"

Actually, if it does not depend on any instance, it can just return some constant value, it does not have to be static.

Just because a static method does not depend on an instance, it does not mean you should use it always for this kind of situation.

Leo
  • 6,480
  • 4
  • 37
  • 52
  • Does this satisfy my condition (2)? I am absolutely intending for the `getIdentity` method to return a constant value, but you will get an error if you try to call the method from a static context. – John Gowers Mar 17 '14 at 16:00
  • I think the point is that you might want to obtain the identity without having any instance available. – Giovanni Botta Mar 17 '14 at 16:06