I am reading DesignPatterns ('GoF patterns') and implementing the Example MazeGame
. While reading about Prototypes, I ran into a thing writing the clone method (cloneIt()
).
我正在阅读DesignPatterns('GoF模式')并实现示例MazeGame。在阅读有关Prototypes的内容时,我遇到了编写克隆方法(cloneIt())的问题。
First of all my structure:
首先我的结构:
Interface: MapSite
AbstractClass: AbstractMapSite
Concrete Impl: Room
, Door
, Wall
混凝土Impl:房间,门,墙
My plan is to define cloneIt
in MapSite
and give a default implementation (simply calling Object.clone()
), which can be overidden in the concrete classes. Now the cloneIt()
method always returns the interface type MapSite
.
我的计划是在MapSite中定义cloneIt并给出一个默认实现(简单地调用Object.clone()),它可以在具体类中被覆盖。现在cloneIt()方法总是返回接口类型MapSite。
Is there a way to 'force' Java to return the concrete class type (Room, Door, Wall
) eventhough the method from the abstract class is used? This may avoid castings.
有没有办法'强制'Java返回具体的类类型(Room,Door,Wall),尽管使用了抽象类的方法?这可以避免铸件。
I know about the pros of Interfaces and why they are used :)
我知道接口的优点以及使用它们的原因:)
Solution
As @philipp-wendler and @davidxxx suggested, I ended up using generics. In case the shallow copy of Object.clone()
is a problem, I override cloneIt()
in the concrete class.
正如@ philipp-wendler和@davidxxx建议的那样,我最终使用了泛型。如果Object.clone()的浅拷贝是一个问题,我在具体类中重写cloneIt()。
public interface MapSite<T> extends Serializable {
T cloneIt();
}
...
public abstract class AbstractMapSite<T> implements MapSite<T> {
public T cloneIt() {
try {
return (T) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
...
public class Wall extends AbstractMapSite<Wall> {
public Wall cloneIt(){
// special code here
}
}
2 个解决方案
#1
1
My plan is to define cloneIt in MapSite and give a default implementation (simply calling Object.clone()), which can be overidden in the concrete classes.
我的计划是在MapSite中定义cloneIt并给出一个默认实现(简单地调用Object.clone()),它可以在具体类中被覆盖。
Be aware : the default implementation of Object.clone()
makes a shallow copy of the cloned object and you should also implement the Cloneable
interface if you don't want to see a CloneNotSupportedException
be thrown.
请注意:Object.clone()的默认实现是克隆对象的浅表副本,如果您不希望看到抛出CloneNotSupportedException,则还应该实现Cloneable接口。
So you should override both clone()
and cloneIt()
. It is confusing because a single method is enough. Just keep cloneIt()
and forget the clumsy clone()
method.
所以你应该重写clone()和cloneIt()。这很令人困惑,因为单一方法就足够了。只需保留cloneIt()并忘记笨拙的clone()方法。
Is there a way to 'force' Java to return the concrete class type (Room, Door, Wall) eventhough the method from the abstract class is used? This may avoid castings.
有没有办法'强制'Java返回具体的类类型(Room,Door,Wall),尽管使用了抽象类的方法?这可以避免铸件。
With Generics yes you can do it.
有了Generics,你可以做到。
For example :
例如 :
public interface MapSite<T>{
T cloneIt();
}
public abstract class AbstractMapSite<T> implements MapSite<T>{
...
}
public class Wall extends AbstractMapSite<Wall>{
public Wall cloneIt(){
...
}
}
#2
1
You need a recursive generic type:
您需要一个递归泛型类型:
public interface MapSite<T extends MapSite<T>> {
T cloneIt();
}
public abstract class AbstractMapSite<T extends AbstractMapSite<T>> implements MapSite<T> {
}
public class Room extends AbstractMapSite<Room> {
public Room cloneIt() { ... }
}
This type forces non-abstract subclasses of MapSite
to declare T
as their own type, thus guaranteeing the correct return type of cloneIt
.
此类型强制MapSite的非抽象子类将T声明为其自己的类型,从而保证cloneIt的正确返回类型。
You could also implement cloneIt
in the abstract class if you call clone()
and use an unchecked cast to T
.
如果调用clone()并使用未经检查的强制转换为T,也可以在抽象类中实现cloneIt。
#1
1
My plan is to define cloneIt in MapSite and give a default implementation (simply calling Object.clone()), which can be overidden in the concrete classes.
我的计划是在MapSite中定义cloneIt并给出一个默认实现(简单地调用Object.clone()),它可以在具体类中被覆盖。
Be aware : the default implementation of Object.clone()
makes a shallow copy of the cloned object and you should also implement the Cloneable
interface if you don't want to see a CloneNotSupportedException
be thrown.
请注意:Object.clone()的默认实现是克隆对象的浅表副本,如果您不希望看到抛出CloneNotSupportedException,则还应该实现Cloneable接口。
So you should override both clone()
and cloneIt()
. It is confusing because a single method is enough. Just keep cloneIt()
and forget the clumsy clone()
method.
所以你应该重写clone()和cloneIt()。这很令人困惑,因为单一方法就足够了。只需保留cloneIt()并忘记笨拙的clone()方法。
Is there a way to 'force' Java to return the concrete class type (Room, Door, Wall) eventhough the method from the abstract class is used? This may avoid castings.
有没有办法'强制'Java返回具体的类类型(Room,Door,Wall),尽管使用了抽象类的方法?这可以避免铸件。
With Generics yes you can do it.
有了Generics,你可以做到。
For example :
例如 :
public interface MapSite<T>{
T cloneIt();
}
public abstract class AbstractMapSite<T> implements MapSite<T>{
...
}
public class Wall extends AbstractMapSite<Wall>{
public Wall cloneIt(){
...
}
}
#2
1
You need a recursive generic type:
您需要一个递归泛型类型:
public interface MapSite<T extends MapSite<T>> {
T cloneIt();
}
public abstract class AbstractMapSite<T extends AbstractMapSite<T>> implements MapSite<T> {
}
public class Room extends AbstractMapSite<Room> {
public Room cloneIt() { ... }
}
This type forces non-abstract subclasses of MapSite
to declare T
as their own type, thus guaranteeing the correct return type of cloneIt
.
此类型强制MapSite的非抽象子类将T声明为其自己的类型,从而保证cloneIt的正确返回类型。
You could also implement cloneIt
in the abstract class if you call clone()
and use an unchecked cast to T
.
如果调用clone()并使用未经检查的强制转换为T,也可以在抽象类中实现cloneIt。