创建`Copyable`类型的接口而不是使用`Cloneable`是否有意义? [英] Does it make sense to create a `Copyable` type interface instead of using `Cloneable`?

查看:112
本文介绍了创建`Copyable`类型的接口而不是使用`Cloneable`是否有意义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些代码需要发送对象的副本。之所以如此,是因为调用的服务(运行时库)会修改发送的对象。如果下面的 doThing 方法需要设置 ImportantObj 类中的任何字段,则该对象还需要公开setter。此实现有待更改,但没有合理的期望在不久的将来进行更改。我的解决方法是提供一个执行以下操作的类:

I have a bit of code that requires a copy of an object be sent in. This requirement is because a service (runtime library) that is called modifies the object sent. This object also needs to expose setters, in case the doThing method below needs to set any field in the ImportantObj class. This implementation is pending change, but does not have a reasonable expectation to be changed in the near future. My workaround is to provide a class that does as follows:

public class DangerousCallWrapper<T> implements DangerousCaller<T> {
  public T doThing(T dataObject) {

      T cloneOfDataObject = #Clone of dataObject

      // This service modifies the cloneOfDataObject... dangerous! 
      Optional<T> result = service.doThing(cloneOfDataObject);

      return result.orElseThrow(() -> new RuntimeException("No data object returned");
  }
}

public interface DangerousCaller<T> {

  /**
  * Performs the functionality of the DangerousService
  */
  public T doThing(T);
}


public DangerousService<T> {


  public T doThing(T data) {
   data.importantField = null;
   data.thing = "Done!";

   return data;
  }
}

public static void main() {

  DangerousService service = new DangerousService<ImportantObj>();
  ImportantObj important = new ImportantObj().setImportantField("Password for my bank account").setThing("Undone");
  service.doThing(important);
  //would fail this check
  assertNotNull(important.importantField);

  DangerousCallWrapper wrapper = new DangerousCallWrapper<ImportantObj>();
  ImportantObj important = new ImportantObj().setImportantField("Password for my bank account").setThing("Undone");
  service.doThing(important);
  //would not fail this check
  assertNotNull(important.importantField);
}

所以该方法的第一行是我遇到的问题。这是一种通用类型,因此我无法明确调用某些克隆实用程序,例如Jackson或类似的程序。

So the first line of that method is where I am stuck. It is a generic type, so I can't explicitly call some cloning utility like Jackson, or similar.

所以我想我只是将 T扩展Cloneable 添加到方法中...但是我打开了 Cloneable 不受限制的蠕虫( https: //www.artima.com/intv/bloch13.html )。我还读过,复制构造函数可能是处理此问题的最佳方法...但是,我不确定如何使用泛型来表示这一点。

So I thought I would just add T extends Cloneable to the method... but I opened the can of worms that Cloneable is beyond taboo (https://www.artima.com/intv/bloch13.html). I have also read that copy constructors are probably the best way to handle this... However, I am unsure of how to denote that using the generics.

所以我的想法是提供一个接口 Copyable ,该接口可以实现您期望的 Cloneable 要做的事情:公开一个方法, copy(),该方法将创建该类的新实例。

So my thought was to provide an interface Copyable that does what you would expect Cloneable to do: expose a method, copy() that will create a new instance of the class.

这是否可行?

推荐答案

要解决您的问题,您需要对 dataObject 像这样:

To solve your problem you need to polymorphically make a copy of dataObject like this:

T cloneOfDataObject = dataObject.clone();

问题是 Cloneable 具有 clone()方法,因此以上代码无法编译。

and the issue is that Cloneable does not have a clone() method, so the above does not compile.

鉴于此前提,创建自己的 Copyable 接口定义 clone()方法,因此您可以在数据对象的类上利用已经实现的 clone()方法(如果存在)。为了获得最大的有效性,该接口也必须是通用的:

Given this premise, it does make sense to create your own Copyable interface that defines a clone() method so you can leverage already-implemented clone() methods (if they exist) on the classes of your data object. For maximum effectiveness this interface would need to be generic as well:

interface Copyable<T> {
    public T clone();
}

以及绑定的类型:

public class DangerousCallWrapper<T extends Copyable<T>> 
    implements DangerousCaller<T> {

这篇关于创建`Copyable`类型的接口而不是使用`Cloneable`是否有意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆