【问题标题】:Transform an object to its subclass in Java在 Java 中将对象转换为其子类
【发布时间】:2016-04-06 12:13:18
【问题描述】:

这不是一个常规问题,请听我解释。

我有一个 Animal 类的对象。如何将其转换为其子类Cat?像这样:

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

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

【问题讨论】:

  • 为什么它们首先是 Animal 实例?如果您可以首先将它们创建为 Cats,那将解决您的问题。
  • Animal c = new Cat();开头?
  • @guitarsteve 不幸的是,我确实在考虑一个不寻常的问题。不像你说的那样。
  • @cricket_007 不幸的是,我确实在考虑一个不寻常的问题。不像你说的那样。

标签: java oop class-hierarchy


【解决方案1】:

忽略一个事实,即在您的示例中,您想要反转原样关系(如“一个苹果是水果”与“一个水果是一个苹果”) - 这在一定程度上是没有意义的。

但是让我们想象一个例子,你必须让一个土豆看起来像一个苹果。所以你要做的就是把所有的果肉都切出来,把土豆放进苹果里(我在这里用水果的例子,因为动物会有点乱)。 这称为代理或包装。

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

静态:一个包装器:

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

动态:代理:

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

使用 Java 动态代理的替代方法是代码生成库,例如 CGLibJavaassist,它们在运行时生成目标类型的子类,这与包装器基本相同,但实现方式类似于代理。

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

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

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

【讨论】:

  • 恐怕你误解了我的观点。您的解决方案非常适合将课程委派给另一个课程。但我的问题更具体。动物是猫的超类。我不需要修改 Cat 的任何方法,我想要的是将常用字段从 Animal 复制到 Cat,而 Cat 的其他唯一字段保持默认。
  • 这行得通!这正是我想要的。反射是一项很棒的技术哈哈。非常感谢。
【解决方案2】:

在子类中创建一个复制构造函数怎么样?

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

Animal 类中声明此类构造函数,并使用super(animal) 将任何子类的控件传递给它,您将在其中定义自定义逻辑。

【讨论】:

  • 这是一个好主意并且易于实施。但事实上我对这些类没有任何写权限。想象一下,我被要求向不属于我的明显来源添加一个功能。
  • 所以你想对你不控制的类的对象进行非法的向下转换。听起来是个不错的计划/s。然后,您会被调用 getter 和 setter 所困,享受吧。
【解决方案3】:

我认为你做得对

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

希望对你有帮助

【讨论】:

  • 这不能回答所问的问题,当然您可以强制转换 Cat 对象以适应 Cat 变量,OP 想要将 Animal 对象放入 Cat变量。
  • 对不起,我的“a”实际上是 Animal 的对象,而不是 Cat 对象的 Animal 引用。
  • @jinge 是否有任何答案可以解决您的问题?如果不是,请提供您的问题的更多详细信息。
  • 谢谢。其中一个答案真的很有帮助,我正在验证它是否解决了我的问题。我会接受或提供更多细节。
猜你喜欢
  • 2022-06-10
  • 2016-09-24
  • 2022-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多