开发者

Refining the return type of a method in a subclass

开发者 https://www.devze.com 2023-04-09 09:34 出处:网络
Say I have the following two classes: public class A { protected A create() { return new A(); } public A f() {

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();
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消