实现在接口中定义的clone返回具体类?

时间:2022-09-02 12:32:08

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。