在 Java 中将对象转换为其子类

Transform an object to its subclass in Java

这不是一般问题,请听我解释。

我有一个对象class Animal。我怎样才能把它转换成它的subclass Cat?像这样:

Animal a = new Animal();
Cat c = (Cat) a;

当然,我知道从Animal直接转换到Cat是不可能的。但我不想手动创建一个新的 Cat 并将字段从 Animal 复制到它。因为有时我有很多 class 层次结构需要转换。怎么用通用的方法解决?

在子class中创建一个复制构造函数如何?

public Cat(Animal animal) { super(animal); }

Animal class 中声明这样的构造函数,然后使用 super(animal) 从任何子 class 向其传递一个控件,您将在其中定义自定义逻辑。

忽略了这样一个事实,即在您的示例中您想要反转原样关系(如 "an apple is-a fruit" 与 "a fruit is-an apple" 中的关系)——这在某种程度上毫无意义。

但是让我们想象一下这样的情况,您必须让土豆 看起来像 苹果。所以你要做的是切掉所有果肉并将土豆放入苹果中(我在这里使用水果示例,因为对于动物来说它会变得有点混乱)。 这称为代理或包装。

这两种技术都可以在 java 中静态或动态地完成。

静态:包装器:

  • 新建 Class,即 VeggiAppleWrapper
  • 让它扩展苹果(所以它包裹的任何东西看起来都像苹果)
  • 定义接受其他类型(即 Potato)的构造函数
  • implement/override 常用方法并将调用委托给包装对象
  • 实施抛出 UnsupportedOperationException 的所有其他方法

动态地:代理:

  • 你必须至少为目标类型定义一个接口(即interface Apple
  • 使用Proxy
  • 创建代理实例
  • 使用已实现接口列表中的Apple接口
  • 实现一个 MethodInvocationHandler 来为您转发,类似于 Wrapper,但使用 Reflection
  • 将代理投射到 Apple

使用 Java 的动态代理的替代方法是代码生成库,例如 CGLib or Javaassist,它会在运行时生成目标类型的子 class,这与包装器但像代理一样实现。

为了仅将值从 animal 复制到 cat 实例(因为 animal 是一个超级class,一些字段应该是通用的),您也可以使用反射 api

for(Field f : Animal.class.getDeclaredFields()) { 
  f.setAccessible(true)
  f.set(cat, f.get(animal));
} 

这只是一个简单的例子,没有异常处理,也没有考虑Animal的superclass的字段(getDeclaredFields只检索了this的字段class).

我觉得你做的对

Animal animal = new Animal();
Cat cat = new Cat();

public void foo(){
  animal = cat; //works because Animal is parent class
  cat = (Cat) animal; //you cast Animal to Cat like as parent to child
}

看看这个https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

希望对你有帮助