我有一个基类:
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());
}
}
但是我希望Moved和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());
}
有没有办法做到这一点?我最初尝试解决这个问题的方法是使形状和位置不再是最终的,并使Moved和Rotated Move和Rotate方法改变这种状态。我真的想让对象变成不可变的,因为它会使我的应用程序的大部分内容更易于管理
答案 0 :(得分:1)
我认为这与仿制药几乎没有关系。您可以将方法声明保留为:
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);
}
答案 1 :(得分:1)
我假设您只想在基类中定义一次泛型方法,并让它们在您的子类中自动运行。
是的,这可以用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);
}
}