Say I have the following two classes:
public class A {
protected A create() {
return new A();
}
public A f() {
return create();
}
}
public class B extends A {
@Override
protected B create() {
return new B();
}
}
So if I call f() on an instance of A, it will return another A. And if I call f() on an instance of B, it will return another B since the B.create() method will be called from A.f(). But, the f() method on B is defined to return an object of type A. so this code will not compile:
A a1 = new A();
B b1 = new B();
A a2 = a1.f();
B b2 = b1.f(); //Type mismatch: cannot convert from A to B
Without having to override the f() method in class B, is there any way I can have A.f()开发者_高级运维 return A, while B.f() returns a B? I've messed around a lot with generics but keep hitting a wall.
Without having to override the f() method in class B, is there any way I can have A.f() return A, while B.f() returns a B?
The only problem is in the very last line of code in your question. Just change
B b2 = b1.f();
// to
A b2 = b1.f();
I think you've tripped over your own code. The create
function versus the f
function was confusing you. The following compiles:
class demo {
public class A {
protected A create() {
return new A();
}
}
public class B extends A {
protected B create() {
return new B();
}
}
void d() {
A a1 = new A();
B b1 = new B();
A a2 = a1.create();
B b2 = b1.create();
}
}
When the co-variant create
was hidden behind the non-co-variant f
, the compiler couldn't "run" the f
function and prove it would always return a B.
You would also have to override f()
as well - your version calls a method that returns A
.
public class B extends A {
@Override
protected B create() {
return new B();
}
@Override
public B f() {
return create();
}
}
精彩评论