我有一个基类:
public abstract class BasePiece extends Serialisable {
public final Position[] shape;
public final Position position;
public abstract Position[] getInitialShape();
public BasePiece() {
position = new Position(0, 0);
shape = getInitialShape();
}
public BasePiece(Position pos, Position[] initialShape) {
position = pos;
shape = initialShape;
}
public BasePiece Moved(Position offset) {
return BasePiece(position.add(offset), shape);
}
public BasePiece Rotated() {
return BasePiece(position, shape.Rotated());
}
}但是,我希望通过移动和旋转来返回继承这个类的类的实例。我对Java比较陌生,并且有一些C#的经验,我尝试做以下事情:
public <T extends BasePiece> T Moved(Position offset) {
return T(position.add(offset), shape);
}
public <T extends BasePiece> T Rotated() {
return T(position, shape.Rotated());
}有什么方法可以做到这一点吗?我最初解决这个问题的尝试是使形状和位置不再是最终的,并使移动和旋转的移动和旋转方法改变这种状态。我真的想让对象变得不可变,因为这将使我的应用程序的许多剩余部分更易于管理
发布于 2014-02-10 05:02:11
我认为这与泛型没有多大关系。您可以将方法的声明保留为:
public BasePiece Moved(Position offset) {
return BasePiece(position.add(offset), shape);
}在扩展它的类中:
class ExtendPiece extends BasePiece {
@Override
public BasePiece Moved(Position offset) {
return ExtendPiece(position.add(offset), shape);
}
}可以由ExtendPiece向下转换为BasePiece。
但是,当然,您必须自己进行强制转换:
ExtendPiece e = (ExtendPiece) obj.Moved(..);编辑:
一种快速的解决方法是使用所谓的双重分派:
让每个子类实现方法newInstance(),这些方法在基类中是抽象的。在ExtendedPiece中:
public BaseClass newInstance(Position pos, Position[] initialShape){
return new ExtendedPiece(pos, initialShape);
}抽象方法的代码如下:
public BasePiece Moved(Position offset) {
return this.newInstance(position.add(offset), shape);
}发布于 2014-02-10 05:50:40
我假设您只想在基类中定义一次泛型方法,并让它们在子类中自动工作。
是的,这可以在Java中完成。它比在C#中更冗长一些,但下面是您如何做到这一点。
首先,您必须将以下代码添加到基类声明中:
public abstract class BasePiece<T extends BasePiece<T>> implements Serializable {
...
}然后,在你的方法中,这样做(它涉及到反射,你必须导入java.lang.reflect.Constructor):
public T Moved(Position offset) {
//Use reflection to invoke the constructor
@SuppressWarnings("unchecked")
Constructor<T> constructor = (Constructor<T>) this.getClass().getConstructor(Position.class, Position[].class);
T newInstanceOfSpecificType = null;
try {
// Cast result to T, which will be the subclass
newInstanceOfSpecificType = (T) constructor.newInstance(position.add(offset), shape);
} catch (Exception e) {
if (e instanceof NoSuchMethodException) {
throw new RuntimeException("You forgot to declare the appropriate constructor in " + this.getClass().getSimpleName() + "!\n");
}
e.printStackTrace();
}
return newInstanceOfSpecificType;
}唯一需要注意的是:您必须确保在所有子类中定义带有签名(Position,Position[])的构造函数,并且必须明确声明您的子类,如下所示:
public class ExtendedPiece extends BasePiece<ExtendedPiece> {
public ExtendedPiece(Posistion position, Position[] shape) {
return super(position, shape);
}
}https://stackoverflow.com/questions/21664959
复制相似问题