How can I implement abstract static methods in Java?

John Gowers :

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?

Jason C :

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.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Why can't static methods be abstract in Java?

Java: how to implement private abstract methods?

How to implement methods of an abstract class? (Java)

How I can stub abstract java class with protected abstract methods via ScalaMock?

Why can't I have abstract static methods in C#?

How can I implement a Java interface with variadic methods in Scala?

How can I get Typescript to recognize that I actually did implement abstract methods when I do it via a decorator?

How do I implement multiple methods of an abstract class efficiently?

How do I implement abstract methods with different parameters/return types

How can I implement static cache in rust?

How can I implement a abstract flagged enum with support for bitwise operations?

Polymorphism and inheritance in Java with static methods of abstract class

How can an abstract implement an interface?

django models - how can i create abstract methods

How to find and implement all the abstract methods in PyCharm?

Do i need to implement all the methods of interface again while inheriting abstract class in Java?

how can i run an abstract method in Python (child will implement it) and abstract hirrachy

How do synchronized static methods work in Java and can I use it for loading Hibernate entities?

How do I implement abstract class inside abstract class in the implementation class in Java?

How can I implement this particular "AnimatedBottomNavigationBar" for Android? Errors with methods

How can I correctly implement the methods in my class?

How can I implement static 'test local' data in an NUnit test?

Do I have to implement all abstract methods in python 2.7?

Can static and abstract keyword used together in java?

how can I use @Enclosed without making methods as static

How can i fix the dispose object error in static methods?

How can I test final and static methods of a utility project?

How can I get Predicate from static methods via reflection?

How can I use descriptors for non-static methods?