extends from generic interfaces - java

What wrong in last row?
interface I1<T>{}
class Class1 implements I1{}
class Class2 extends Class1 implements I1{} //valid
class Class3 implements I1<Number>{}
class Class4 extends Class3 implements I1<Number>{} //valid
class Class5 implements I1<Number>{}
class Class6 extends Class5 implements I1<Integer>{} //not valid
class Class7 implements I1{}
class Class8 extends Class7 implements I1<Number>{} // not valid
class Class9 implements I1<Number>{}
class Class10 extends Class9 implements I1{} // not valid !!!
Why I cannot make so?
I saw it in book, but there are not explanation of this thing - only for information.
P.S.
exception text:
java: GenericsTest.I1 cannot be inherited with different arguments:
<java.lang.Integer> and <java.lang.Number>

There are two points to understanding this:
Java generics are normally type-invariant. This means that, for example, an I1<Number> and an I1<Integer> are distinct types. For most purposes, they are unrelated, despite that Integer extends Number.
If an interface is declared as being implemented on a superclass, it can be declared to be implemented again on a subclass. It's redundant but it's allowed.
Now, what is not allowed is implementing an interface twice, where the generic type of the interface is different.
For example, this is not allowed:
class NotAllowed implements I1<String>, I1<Integer> {}
The types of I1 are erased at run time so you cannot do that. At run time there is not really a difference between an I1<String> and an I1<Integer>. Both of them become just I1.
Your example with Class5 and Class6 is not allowed for the same reason as the above NotAllowed is not allowed. It implements the same interface twice but with different generic types.
If it were allowed, it would be paradoxical, because for example given the following:
interface Face<T> {
public void method(T t);
}
If I then implement this twice with different types, it would imply there must be two generically-typed implementations of method:
class Implementation
implements Face<String>, Face<Integer> {
#Override
public void method(String s) {}
#Override
public void method(Integer i) {}
}
This is paradoxical because erasure also dictates that both implementations of method will become identical at run time. You cannot have methods with identical signatures declared in the same class so it's not allowed.

class Class1 implements I1{}
class Class2 extends Class1 implements I1{}
This one is obvious, it means that Class2 implements I1{}. It does it explicitly by saying implements I1{} but also implicitly by extending Class1, which implements I1{} as well. There's no problem since they both implement the same interface, it's not ambiguous.
class Class3 implements I1<Number>{}
class Class4 extends Class3 implements I1<Number>{}
This is the same flavor as above. It says Class4 implements I1<Number>. It's specified implicitly and explicitly as above. But it's not ambiguous, it's I1<Number>
Of course, it's redundant because it uses two way simultaneously to define that Class4 implements I1<Number>. You could just do class Class4 extends Class3 and it'd be exactly the same.
Now with this one it's different:
class Class5 implements I1<Number>{}
class Class6 extends Class5 implements I1<Integer>{}
It says Class6 is implementing both I1<Integer> (explicitly) and I1<Number> (implicitly through extending Class5). It can't be at the same time. Imagine for example that I1 has a method: public X something(). It's signature in I1<Number> would be public Number something() and in I1<Integer> it would be public Integer something(). This would lead to a duplicate method. It's therefore invalid. If you implement a generic interface, you can only implement it once, no matter the generic type.
I hope this helps illustrate why it's invalid.
EDIT
First, understand that I1 is semantically the same as I1<Object>.
Then, understand that I1<A> is not the same as I1<B>
Also, understand that all your invalid examples can be summarized (for reasons explained above) with:
class X implements I1<A>, I1<B>
Why is that invalid? Because it may create ambiguity in the signatures. If I1 looked like this:
public interface I1<T> {
public T something();
}
Then X would have to look something like:
class X implements I1<A>, I1<B> {
public A something() { return null; }
public B something() { return null; }
}
Now, if I did:
X x = new X();
x.something();
Which of the two methods is is calling? You can't tell, because it is ambiguous. The Java language just doesn't give you the opportunity to define ambiguous APIs. Therefore, you can't implement both I1<A> and I1<B>.

because of Type Erasure implementing one interface with two different generic parameter is impossible.

Related

Java : generic type with type parameters?

I have a class like this :
public class MyClass <T extends Model1, X extends Model2> {
private CommonMessage<T,X> someMethod() {
....
}
}
Now I have a customized message type MyMessage extends CommonMessage, so I want to know how to have generic type that still having T and X as parameters ? For example :
public class MyClass <M extends CommonMessage, T extends Model1, X extends Model2> {
private M<T,X> someMethod() {
....
}
}
Short answer:
First of all as CommonMessage is generic, extending it in a non-generic way is very bad so you should have done M extends CommonMessage<T, X> And this way because type parameter passed to CommonMessage at class declaration you should not mention this parameter type again at method return type so method return type should be M.
Long answer:
I know you do know this definitions but sometimes we as human forget simple things. First we should consider what generics are created for, with generics we can create classes with different parameter types, this parameter types will be provided when they are extended by another class or when we create new instance of them with new() operator, so when we are writing our class we don't know the exact type for those parameter and we want to delay this decision until later, it is contradictory to something you are doing in your class because here your method is private and you can't change its implementation in your child class(the class which inherited from your class). But know we can change your implementation to something like this which will be compiled well:
public class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
private M method1(){
...
}
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}
although this implementation will be compiled the problem is that when you are writing your private method(method1) you don't know what is the type of M at the time of writing this class because it will be passed when we want to create new instance of this class or when we inherit another class from this class. so what type of Object do you want to create and return in your method1? the only thing that you know here is that its type is M which extends CommonMessage but you don't know what the exact type of M is at the time of writing your private method(method1)!
And on the top of that you can't delegate this decision to your subclass(because this method is private). Now the question is that why it is allowed and compiled well when we don't know the exact type of M? for a moment forget this question I will make it clear after explaining correct approach. so what is the correct approach? Think about it, the person who write subclass does know exactly what the type of parameter M is and they can create appropriate instance of M in implementation of method1 to return from this method. so why not delegate this decision to subclass and making this method abstract? This completely make senses. in a nutshell we have some implementation like this:
public abstract class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
public abstract M method1();
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}
now lets get back to our question why first program that I suggested to you compiled well? why we are allowed to have private method that its return type is generic that will be passed at instanciation or inheritance time?
because there are a lot of situations that make it correct and appropriate.
one situation is that our private method call another public method which return the appropriate type, like this:
public abstract class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
private M method1(){
return method2();
}
abstract M method2();
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}

Java Inheritance with generics

Can somebody explain (like for dummies) the following examples of inheritance in Java:
1) public class Dog <T extends Animal> {....
2) public class Buldog extends Dog<DogFood, DogCommands> {....
3) public class Buldog<T extends DogFood, K extends DogCommands> extends Animal implements LivingBeign, LivingThing<T,K> { ....
1) public class Dog <T extends Animal> {...
There will be an generic type In your Dog class which is inherit variables and methods from class (probably an abstract class Animal)
This T must have and animal property.. For example assume you have a class Mammalian. We know that all mammalian are animal so they have what all animals have, and they can what all animals can.
So yo can call this as
public Dog<Mammalian> myDog = ...
There is a different situation.
2) public class Buldog extends Dog<DogFood, DogCommands> {....
So your dog class should be written like
/** T refers the food, and K refers commands*/
public class Dog<T,K> {....
So when you want to extend your class with Bulldog, you can leave generic or specify those generic types..
3) public class Buldog<T extends DogFood, K extends DogCommands> extends Animal implements LivingBeign, LivingThing<T,K> { ....
This is also as easy as above codes. The difference that you are desiring subclass of DogFood, which can be anyting, it can be Pap or Milk or Meat, and some subclass of DogCommands for example SitCommand, PlayCommand.. And as you are creating Buldog you know that It is Animal, so you don't want to write animal's property and methods again and since in Java you can't multiple inherit, you want also the other interfaces methods in your class..
I hope it is more understandable now.

Interface extending a class

Let's say that I have an interface, and all classes that implement that interface also extend a certain super class.
public class SuperClass {
public void someMethod() {...}
}
public interface MyInterface {
void someOtherMethod();
}
//many (but not all) sub classes do this
public class SubClass extends SuperClass implements MyInterface {
#Override
public void someOtherMethod() {...}
}
Then if I'm dealing with an object of type MyInterface and I don't know the specific sub class, I have to hold two references to the same object:
MyInterface someObject = ...;
SuperClass someObjectCopy = (SuperClass) someObject; //will never throw ClassCastException
someObjectCopy.someMethod();
someObject.someOtherMethod();
I tried making the interface extend the super class, but it's a compiler error:
public interface MyInterface extends SuperClass {} //compiler error
I also thought of combining the interface and the super class into an abstract class like so:
public abstract class NewSuperClass {
public void someMethod();
public abstract void someOtherMethod();
}
But then i can't have a sub class that doesn't want to implement someOtherMethod().
So is there a way to signify that every class that implements an interface also extends a certain class, or do I have no choice but to carry around two references to the same object?
I think that the only solution you have would be to have a reference to both, but this indicates that you have a design flaw somewhere. The reason I say is because you should think of an interface as something that your implementing classes will always need. For example, a Car and Airplane both need a Drive() interface. A design reconsideration is probably worth your time. However, if you still want to follow that path, you can do the following:
public class ClassA {
public void methodA(){};
}
public abstract class ClassB extends Class A{
public void methodB();
}
After you have the above setup, you can now reference an object that has the two methods by doing the following:
ClassB classB = new ClassB();
classB.methodA();
classB.methodB();
Now you don't actually have to actually use two pointers to the same object.

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.

Java Abstract Class Implementing an Interface with Generics

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'

Categories