实现基类方法的java方法可以返回一个继承的类吗?

时间:2013-12-17 21:49:55

标签: java inheritance

假设我有标准的Draw类,继承了Circle和Square类。有办法做到以下几点吗?也许用泛型?

class Draw {
  public abstract Draw duplicate();
}

class Circle extends Draw {
  public Circle duplicate() {
    return new Circle();
  }
}

class Square extends Draw {
  public Square duplicate() {
    return new Square();
  }
}

4 个答案:

答案 0 :(得分:4)

是的,你可以从Java 5开始。

从Java 5开始,子类中的方法可能返回一个对象,该对象的类型是由超类中具有相同签名的方法返回的类型的子类。 (source)。这称为协变返回类型。

答案 1 :(得分:4)

是的,可以让重写方法返回一个类型,该类型是超类方法的返回类型的子类。称为“协变返回类型”的这种技术被描述为at the bottom of a Java tutorial on return types。这是因为CircleSquareDraw s,所以即使你有一个超类引用,并且你不知道或不关心你真正拥有哪个子类,你仍然是保证可以取回Draw

顺便说一句,要让您的代码进行编译,您只需要创建Drawabstract。其他所有内容,包括协变返回类型,看起来都不错。

答案 2 :(得分:1)

我会在这里使用泛型:

class Draw<T> {
  public abstract T duplicate();
}

class Circle extends Draw<Circle> {
  @Override
  public Circle duplicate() {
    return new Circle();
  }
}

class Square extends Draw<Square> {
  @Override
  public Square duplicate() {
    return new Square();
  }
}

答案 3 :(得分:1)

我认为您想要做的是以下内容:

public abstract class Draw<T extends Draw> {
    public abstract T duplicate();
}

public class Circle extends Draw<Circle> {
    @Override
    public Circle duplicate() {
        return new Circle();
    }
}

public class Square extends Draw<Square> {
    @Override
    public Square duplicate() {
        return new Square();
    }
}
  1. 使用泛型(T上的约束,应该扩展Draw,以避免奇怪的继承,例如Circle extends Draw<List>
  2. abstract关键字添加到Draw
  3. 然后,您可以执行以下操作:

    Square originalSquare = new Square();
    Circle originalCircle = new Circle();
    
    Square duplicatedSquare = originalSquare.duplicate();
    Circle duplicatedCircle = originalCircle.duplicate();
    

    修改

    如果没有泛型,你可以这样做:

    public abstract class Draw {
        public abstract Draw duplicate();
    }
    
    public class Circle extends Draw {
        @Override
        public Circle duplicate() {
            return new Circle();
        }
    }
    
    public class Square extends Draw {
        @Override
        public Square duplicate() {
            return new Square();
        }
    }
    

    感谢Pavel,rgettman和Enno Shioji,我不知道“协变返回类型”。