2

I have the following interface :

public interface ClusterPopulation
{
    public double computeDistance(ClusterPopulation other);
}

Is it possible to specify within the interface itself, that implementation A of ClusterPopulation can only take A implementation as argument of computeDistance ?

The only approching solution that I see is the following, but I don't like it :

Redefine interface with generics:

public interface ClusterPopulation
{
    public <T extends ClusterPopulation> double computeDistance(T other);
}

Within the implementation, throw IllegalArgumentException if argument is not from the good type, do some casts if type is ok... Meeeeh !

Even with this approach, end-user is only aware of the constraint by reading the documentation/looking at code implementation/trial and error...

Any better solution ?

David
  • 1,138
  • 5
  • 15
  • http://stackoverflow.com/questions/7354740/is-there-a-way-to-refer-to-the-current-type-with-a-type-variable – biziclop Mar 30 '16 at 20:34

2 Answers2

5

You had the right idea with using generics, but instead of applying it to the method, apply it to the whole interface.

public interface ClusterPopulation<T extends ClusterPopulation<T>>
{
    double computeDistance(T other);
}

That allows an implementation to define T as itself.

public class ClusterPopulationA implements ClusterPopulation<ClusterPopulationA> {  // ...

However, it doesn't disallow an implementation to define it as something else.

public class BreaksPattern implements ClusterPopulation<ClusterPopulationA>

Include in your documentation that all subclasses should define the type parameter T as its own class.

rgettman
  • 176,041
  • 30
  • 275
  • 357
0

In my view, there is a flaw in your design that causes problems. From what you have provided, it seems that ClusterPopulation should be a class, not an interface. Lets look at this method,

public double computeDistance(ClusterPopulation other);

What does this mean? It means that an object of type ClusterPopulation is passed to this method. Furthermore, this object must have some attributes, otherwise how would you compute the distance from this object if it doesn't? Combining these two observations, one can conclude that ClusterPopulation should be a class in order to have an object of that type. When I say a class, it can be concrete or abstract. Let's take the case for abstract class.

public abstract class ClusterPopulation
{
    // common attributes, if any

    abstract public double computeDistance();
}

public class A extends ClusterPopulation {

    public double computeDistance() {
        // do some computation based on ClusterPopulation attributes

    }

}

public class B extends ClusterPopulation {

     public double computeDistance() {
        // do computation based on ClusterPopulation attributes

     }

}

Now, you would use it this way:

ClusterPopulation a = new A();
ClusterPopulation b = new B();

double aResult = a.computeDistance();
double bResult = b.computeDistance();

Notice that the restriction you require is enforced here. Although both a and b are objects of type ClusterPopulation, computeDistance() works only with the concrete type of the calling object.

Nazar Merza
  • 3,365
  • 1
  • 19
  • 19