Java Abstract Class Implementing an Interface with Generics - java

I am trying to define an abstract class implementing Comparable. When I define the class with following definition:
public abstract class MyClass implements Comparable <MyClass>
subclasses have to implement compareTo(MyClass object). Instead, I want every subclass to implement compareTo(SubClass object), accepting an object of its own type. When I try to define the abstract class with something like:
public abstract class MyClass implements Comparable <? extends MyClass>
It complains that "A supertype may not specify any wildcard."
Is there a solution?

It's a little too verbose in my opinion, but works:
public abstract class MyClass<T extends MyClass<T>> implements Comparable<T> {
}
public class SubClass extends MyClass<SubClass> {
#Override
public int compareTo(SubClass o) {
// TODO Auto-generated method stub
return 0;
}
}

Apart from the mechanical difficulties you're encountering declaring the signatures, the goal doesn't make much sense. You're trying to establish a covariant comparison function, which breaks the whole idea of establishing an interface that derived classes can tailor.
If you define some subclass SubClass such that its instances can only be compared to other SubClass instances, then how does SubClass satisfy the contract defined by MyClass? Recall that MyClass is saying that it and any types derived from it can be compared against other MyClass instances. You're trying to make that not true for SubClass, which means that SubClass does not satisfy MyClass's contract: You cannot substitute SubClass for MyClass, because SubClass's requirements are stricter.
This problem centers on covariance and contravariance, and how they allow function signatures to change through type derivation. You can relax a requirement on an argument's type—accepting a wider type than the supertype's signature demands—and you can strengthen a requirement on a return type—promising to return a narrower type than the supertype's signature. Each of these freedoms still allows perfect substitution of the derived type for the supertype; a caller can't tell the difference when using the derived type through the supertype's interface, but a caller using the derived type concretely can take advantage of these freedoms.
Willi's answer teaches something about generic declarations, but I urge you to reconsider your goal before accepting the technique at the expense of semantics.

see Java's own example:
public abstract class Enum<E extends Enum<E>> implements Comparable<E>
public final int compareTo(E o)
on seh's comment: usually the argument is correct. but generics makes type relations more complicated. a SubClass may not be a subtype of MyClass in Willi's solution....
SubClassA is a subtype of MyClass<SubClassA>, but not a subtype of MyClass<SubClassB>
type MyClass<X> defines a contract for compareTo(X) which all of its subtypes must honor. there is no problem there.

I'm not sure that you need the capture:
First, add the compareTo to the abstract class...
public abstract class MyClass implements Comparable <MyClass> {
#Override
public int compareTo(MyClass c) {
...
}
}
Then add the implementations...
public class MyClass1 extends MyClass {
...
}
public class MyClass2 extends MyClass {
...
}
Calling compare will call the super type method...
MyClass1 c1 = new MyClass1();
MyClass2 c2 = new MyClass2();
c1.compareTo(c2);

public abstract class MyClass<T> implements Comparable<T> {
}
public class SubClass extends MyClass<SubClass> {
#Override
public int compareTo(SubClass o) {
// TODO Auto-generated method stub
return 0;
}
}

Found another solution:
Define an interface on the fields which make up the comaprable (e.g ComparableFoo)
Implement the interface on the parent class
Implement Comparable on the parent class.
Write your implementation.
Solution should look like this:
public abstract class MyClass implements ComparableFoo,Comparable<ComparableFoo> {
public int compareTo(ComparableFoo o) {
// your implementation
}
}
This solution implies that more things might implement ComparableFoo - this is likely not the case but then you're coding to an interface and the generics expression is simple.

I know you said you want "compareTo(SubClass object), accepting an object of its own type", but I still suggest declaring the abstract class like this:
public abstract class MyClass implements Comparable <Object>
and do an instanceof check when overriding compareTo in MySubClass:
#Override
public int compareTo(Object o) {
if (o instanceof MySubClass)) {
...
}
else throw new IllegalArgumentException(...)
}
similarly to 'equals' or 'clone'

Related

Create java method that only accepts non-abstract Class types

In Java, is it possible to create a method / a signature that accepts all non-abstract Class types?
Something a la this:
public Object getInstance(Class<? extends ConcreteClassSuperType> someNonAbstractClass){
//some logic that can safely assume that the Class object is not an interface type nor an abstract class
}
where ConcreteClassSuperType is just a fictional type made up to illustrate my intend. Using ? extends Objecthere does not solve the problem.
Elaboration:
In the case at hand the problem was a bit more specific in that my signature dit not have to accept ALL concrete classes but only those implementing some interface, i.e. I was trying to create a signature that accepts the Class type of a class that implements MyInterface. So one could fx pass MyClass.class, where MyClass implements MyInterface. Two problems occured:
The signature will also accept MyInterface.class (since the generics Class<? extends MyInterface> is not a strict upper bound)
One can pass the class type of another interface that extends MyInterface.
Because classes can have multiple parameters, I think it is easier first just to check if the class is concrete and then implement a means to instantiate it. Like,
public <T> boolean isConcrete(Class<T> c) {
if (c.isInterface() || (c.getModifiers() & Modifier.ABSTRACT) == Modifier.ABSTRACT)
return false;
return true;
}
Hope this helps.
EDIT
Sorry just noticed in another comment you could simplify this...
public <T> boolean isConcrete(Class<T> c) {
if (c.isInterface() || Modifier.isAbstract(c.getModifiers()))
return false;
return true;
}

Java generics - what is the difference?

Consider that I have following interface:
public interface MyInterface<T extends Number>
In another class I want to declare a method like this:
public <T extends MyInterface<?>> void abc(T a);
Is this a correct way? Or maybe should I write:
public <T extends MyInterface<T>> void abc(T a);
What is the difference between these two declarations?
Some interfaces are intended to take the implementing class as the generic type.
For instance, the Comparable interface is usually implemented as:
class MyClass implements Comparable<MyClass>
because then the method
int compareTo(T o);
declared in Comparable can be used to compare an instance of MyClass to another instance of the same class.
Other interfaces have a generic parameter of a different type. For instance, List<T>, where T indicates the type of object contained within the list.
If you declare a method with:
public <T extends MyInterface<T>> void abc(T a);
then you're saying that the class T implements the interface MyInterface in the way that classes implement the Comparable interface - with themselves as the generic type. That might or might not be appropriate depending on what MyInterface actually is.
If you declare a method with:
public <T extends MyInterface<?>> void abc(T a):
then you not placing any constraint on the generic type in T's implementation of MyInterface.
The other option is
public void abc(MyInterface<?> a);
which is the simplest way to write a method that will accept any implementation of MyInterface.

Java inheritance; passing a subclass to an abstract method of a superclass

Sorry for the title, couldn't come up with anything clearer.
I have the following structure:
public interface Vehicle {...}
public class Car implements Vehicle {...}
then:
public abstract class Fixer {
...
abstract void fix(Vehicle vehicle);
...
}
and would like to have:
public class CarFixer extends Fixer {
void fix(Car car) {...}
}
but this doesn't work. Eclipse says: The type CarFixer must implement the inherited abstract method Fixer.fix(Vehicle). Any idea how can I solve this?
You can use Generics to solve this:
public abstract class Fixer<T extends Vehicle> {
abstract void fix(T vehicle);
}
public class CarFixer extends Fixer<Car> {
void fix(Car car) {...}
}
The problem with your original version is that the fix method allows any type of vehicle, but your implementing class allows only cars. Consider this code:
Fixer fixer = new CarFixer();
fixer.fix(new Bike()); // <-- boom, `ClassCastException`, Bike is a vehicle but not a car
You've met the humble home of generics.
Generics provide kind of 'wildcard' type where a class or method can specify that 'we don't really care what type it is, we just need -a- type'.
Generics allow a super class to enforce a specific type in a child class instead of allowing any class that extends a certain class.
This means that you're ultimately enforcing a new highest allowed super-class as the parameter (i.e. Vehicle is no longer the most basic allowable type you can pass to fix(); it's now whatever the subclass says it is, so long as that arbitrary type extends Vehicle).
Common places for generics are container classes (i.e. List, Map, and Set) where the container doesn't really care about what type it tracks, but rather focuses on actually tracking and managing those instances.
Generics consist of one or more type placeholders (in Java, E and T are commonly used but the name doesn't really matter; they usually follow the normal type naming conventions) that are used in place of a specific class or super class.
In your code, you want subclasses to implement methods given their exact relevant types (i.e. a CarFixer would take Cars, a JetpackFixer would take Jetpacks) but you want to enforce that these types extend Vehicle.
In order to enforce this, you have to tell the Fixer class exactly what your subclass wants.
public abstract class Fixer <E extends Vehicle>
{
abstract void fix(E vehicle);
}
Your subclass then extends Fixer, filling in E with the type it wants.
public class CarFixer extends Fixer<Car>
{
#Override
void fix(Car vehicle)
{
// ...
}
}

Abstract Inheriting form of Comparable Interface

I understand how to use the Comparable<T> interface, but in this specific example, I'm wondering if there is a way to require the inheriting Class from an Abstract Class (which implements the Comparable<T> interface) to be Comparable against itself.
Let me reiterate, there is an Abstract Class that implements the Comparable Interface:
public abstract class MyAbstractClass implements Comparable<MyAbstractClass>
And a Class which inherits from this Abstract Class:
public class MyClass extends MyAbstractClass
Typically with this setup, the following method is required to satisfy the Comparable Interface:
public int compareTo(MyAbstractClass otherAbstractObject)
This requires me to make the following cast:
public int compareTo(MyAbstractClass otherAbstractObject)
{
MyClass otherObject = (MyClass) otherAbstractObject;
// Comparison...
return result;
}
Given the fact that this cast could easily fail by trying to use a different child of MyAbstractClass, I would like to be able to define my Abstract Class to accept the following method:
public int compareTo(MyClass otherMyObject)
{
// Comparison...
return result;
}
And ideas on how to accomplish this? Or is it simply not possible?
You can define MyAbstractClass using generics as follows:
public abstract class MyAbstractClass<T extends MyAbstractClass<T>>
implements Comparable<T> {
Then you can define subclasses such as
public class MyClass extends MyAbstractClass<MyClass>
which allow you to define the compareTo method like this:
public int compareTo(MyClass otherMyClass)
However, that doesn't prevent anyone from writing a subclass that doesn't conform to the pattern:
public class SneakyClass extends MyAbstractClass<MyClass>
which would also define the compareTo method similarly:
public int compareTo(MyClass otherMyClass)
Note: There's nothing that can force the generic type parameter of a class to equal the class on which it's defined; the best you can do is to enforce an upper bound on the abstract class, to at least force it to be some kind of MyAbstractClass.

AbstractFactory with generic types in Java: a design problem

I have the following 2 interfaces accordingly to abstract factory pattern:
public interface GenericObjectInterface<T extends Number>{
public T getResult();
}
public interface AbstractFactoryInterface{
public <T extends Number> GenericObjectInterface<T> createGenericObject();
}
I have an abstract class implementing GenericObject, but it's still unaware of the concrete type (it does only generic operations on Number):
public abstract class GenericAbstractClass<T extends Number> implements GenericObjectInterface<T>{ }
Then I have a series of concrete class extending that perform generic parameter substitution:
public class IntegerObject extends GenericAbstractClass<Integer>{
public Integer getResult(){}
}
....
Now, from inside an implementation of the factory I build the concrete type, that's implementing GenericObjectInterface but has lost it's generic parameter:
public class ConcreteFactory{
public <T extends Number> GenericObjectInterface<T> greateGenericObject(Class<T> c){
if (c.class.isInstance(Integer.class)){
IntegerObject obj = new IntegerObject();
//I would like to return obj
GenericObjectInterface<T> a = new IntegerObject(); //errror
GenericAbstractClass<T> a = new IntegerObject(); //errror
return a;
}else if (c.class.isInstance(Double.class)){
}
}
}
I would like to return obj that implements GenericObjectInterface but I don't know how can I do it.
how can I solve this?
I'm used to abstract factory but I've never used it with generics. Am I doing some mistakes in interpreting the pattern?
If your method returns an IntegerObject why don't you just return GenericObjectInterface<Integer>? You already know the parameter type.
In that case, just add a generic parameter to AbstractFactoryInterface, too:
public interface AbstractFactoryInterface<T extends Number> { ... }
public class ConcreteFactory implements AbstractFactoryInterface<Integer> { ... }
In your implementation the type of T would be inferred from the assignment, and thus you could do this:
GenericObjectInterface<Double> g = new ConcreteFactory().greateGenericObject();
In that case T would be Double but you'd use Integer internally, resulting in this:
GenericObjectInterface<Double> a = new IntegerCell();
Since the compiler can't ensure that T will always be of type Integer it won't allow you to do that assignment.
Abstract factory is characterized by the factory method returning an interface or abstract class reference instead of the concrete reference. It does not extend to type parameters.
Think of it this way: should you be able to do this?
public class ConcreteListFactory {
public <T> List<T> createList() {
return new ArrayList<String>();
}
}
What if the caller wanted a List<Integer>?
If you want your factory to return a generified type, you should have your concrete class accept the type parameter. Otherwise have your factory method return a GenericObjectInterface<Integer>.
Alternatively, you could have your method accept a type token (Integer.class). For example:
public <T extends Number> GenericObjectInterface<T> createGenericObject(Class<T> clazz) {
if ( clazz.equals(Integer.class) ) {
return (GenericObjectInterface<T>) new IntegerObject();
}
}
This will result in an unchecked cast warning but you can prove to yourself that it is safe, and thus suppress the warning or ignore it.
Generally, factories are not implemented as generics because you can't examine the type of the generic to determine the type of object to create (you can't do T.getClass) which is why #Mark's example causes the class to be passed in as an argument.
I think, more usually you would have multiple concrete factories. One for each Number type that you intend to support.
public interface AbstractFactoryInterface<T extends Number> {
public GenericObjectInterface<T> createGenericObject();
}
class IntegerFactory implements AbstractFactoryInterface<Integer>...
class LongFactory implements AbstractFactoryInterface<Long>...
You could then create a Map<Class, AbstractFactoryInterface>...
Map<Class, AbstractFactoryInterface> myMap = ...;
myMap.put(Integer.class, new IntegerFactory());
myMap.put(Long.class, new LongFactory ());
casting is perfectly fine here. if c==Integer.class, then T=Integer, casting GOI<Object> to GOI<T> is absolutely correct. It is a checked cast because you have checked that T=Integer before casting, therefore the unchecked warning can be legitimately suppressed.

Categories