2013-12-17 123 views
5

比方说,我有标准的Draw类和Circle和Square的继承类。有没有办法做到以下几点?也许用泛型?实现基类方法的java方法能返回一个继承类吗?

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

绘制应该是一个抽象类。否则它看起来很好 – k2col

回答

4

是的,可以有一个覆盖方法返回一个类型,该类型是超类方法返回类型的子类。这种称为“协变返回类型”的技术被描述为at the bottom of a Java tutorial on return types。这是有效的,因为CircleSquareDraw s,所以即使你有一个超类参考,并且你不知道或关心你真的有哪个子类,你仍然可以保证返回Draw。顺便提一下,为了让你的代码编译,你只需要制作Drawabstract。其他一切,包括协变返回类型,看起来都很好。

+0

哦哇,这是超级简单。这是永远在Java中的缺点,你不知道这些新事情发生的时间。谢谢。 –

4

是的,你可以因为Java 5的

由于Java 5,子类中的方法可能会返回一个对象,其类型是方法与在相同签名的返回类型的子类超类。 (source)。这被称为协变返回类型。

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

嘿亚历克斯,你可以扩展为什么你会使用泛型?看起来多余。 – bcorso

+0

基于超类没有泛型的类型安全实用方法... –

+0

类似于'public static > T duplicate(T draw){return draw.duplicate(); } –

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

然后,您可以执行以下操作:

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,我不知道“协变返回类型”。

+0

你真的读过其他的答案吗?你可以在不使用泛型的情况下做你正在描述的内容。 –

+0

在写我自己的答案之前,我还没有看到其他答案。我不知道协变返回类型,谢谢。 – ssssteffff