如何在Java中将父类转换为子类

26

我正在做这件事:

Child child = (Child)parent;

当我这样做时,遇到了错误,我发现不能像这样做。我不确定为什么,但我认为应该是可能的,如果Child类继承自Parent类,则它包含Parent对象数据。

我的问题是:

  • 为什么它不起作用?


  • 如何使其工作,而无需像这样设置每个父属性
class Parent{
    public int parameter1;//...
    public int parameter1000;
}

class Child extends Parent
{
    public Child(Parent parent)
{
        this.parameter1 = parent.parameter1;//...
        this.parameter1000 = parent.parameter1000;
}
}

3
如果“parent”确实是指一个“Child”实例,那么就可以像这样做。 - Oliver Charlesworth
parent 是什么类型? - Mureinik
我有一些从文件中加载的数据,类似于: public Parent loadMe() { Parent p = new Parent(); ... return p; } 然后我需要将这个父对象重新转换为它的某些子对象。 - likaa
你试图做的事情是不可能的。狗是一种动物,但动物不一定是狗。强制类型转换并不能神奇地将一个对象类型转换为另一个对象类型。它只是告诉编译器,你比编译器更清楚对象的实际类型。如果你需要一个“Child”,那么你需要执行new Child()而不是new Parent() - Jesper
如果您分享更多的代码,可能会更清楚您实际想要做什么。如果您的数据加载代码只创建Parent类的实例,则无法将这些对象转换为Child类。您是否真的需要继承?您可以在父类上有一个名为“type”的字段来确定所涉及的对象(子类)的类型吗? - Mick Mnemonic
显示剩余2条评论
3个回答

30

好的,你可以这样做:

Parent p = new Child();
// do whatever
Child c = (Child)p;

或者,如果您必须从一个纯粹的父对象开始,您可以考虑在您的父类中拥有一个构造函数并调用:

class Child{
    public Child(Parent p){
        super(p);
    }
}
class Parent{
    public Parent(Args...){
        //set params
    }
}

或者是组合模式:

class Child {
    Parent p;
    int param1;
    int param2;
}

在这种情况下,您可以直接设置父级。

您还可以使用Apache Commons BeanUtils来执行此操作。使用其BeanUtils类,您可以访问许多实用程序方法,通过反射填充JavaBeans属性。

要将父对象的所有常见/继承属性复制到子类对象中,您可以使用其静态copyProperties()方法,如下所示:

BeanUtils.copyProperties(parentObj,childObject);

请注意,这是一项较为繁重的操作。


嗯,这是可能的,但仍需逐行设置参数。 - likaa
int字段是用来做什么的?@likaa - Stephan D.
我在父类中并没有真正的int字段,而是有不同的属性,其中一些是不同的类型,如果我只有int参数,我会将其放入数组中。 - likaa
你也可以从继承模型转向组合模型。 - Akash Roy Choudhury
@AkashRoyChoudhury 这是一个非常好的想法,如果我找不到更好的解决方案,我会使用它! - likaa
@likaa 好的,所以你只是想要一个简单的方法来设置属性。请查看更新后的答案。 - Akash Roy Choudhury

0
在您的子构造函数中将“this”更改为“super”,并删除父参数,而是用两个参数替换它 int parameter1;//...int parameter1000; :)
class Parent{
public int parameter1;//...
public int parameter1000;
}

class Child extends Parent
{
    public Child(int parameter1, int parameter1000)
    {
        super.parameter1 = parameter1
        super.parameter1000 = parameter1000;
    }
}

我想我不理解你的回答,我想表明我的父类有多个参数(这就是为什么有parameter1 ... parameter1000),我的问题是如何在不设置这些参数的情况下完成它,而不需要1000行代码。 - likaa
如果父类的字段是私有的,会怎样? - fuat

0

你真的想将你的父类转换为子类吗?如果给定的对象(作为父对象给出)是作为子类创建的,则可以在不进行转换的情况下访问正确的函数。这里有一个例子: 在主函数中,您可以看到一个向量“ps”来存储父对象,但添加的是从父类继承的子对象。当迭代该向量时,我不知道下一个子对象是哪种类型(因此无法转换为正确的类),但由于调用的函数具有覆盖关键字,因此使用了正确的子类/方法。

import java.util.Vector;
import lib.Parent;
import lib.C1;
import lib.C2;

public class MyClass {
    public static void main(String []args){
        System.out.println("Hello World");
        C1 c1 = new C1();
        C2 c2 = new C2();
        
        ps.add(c1);
        ps.add(c2);
        
        for(int k = 0; k < ps.size(); k++){
            ps.get(k).setInteger(); // no cast needed
            System.out.println("stored entity " + ps.get(k).i);
        }
        // or use a ranged for loop
        for(Parent p: ps){
            p.setInteger();
            System.out.println("stored entity " + p.i);
        }
    }
     
    static Vector<Parent> ps = new Vector<>();
}

父类:关键字abstract强制每个子类实现该方法,因此如果您有一个父对象,可以安全地调用此方法。由于父类本身是抽象的,因此您不会拥有仅为父对象的对象,因为这是不允许且无法编译的。
package lib;
public abstract class Parent{
    public Integer i;
    
    public abstract void setInteger();
}

这里有两个子类,它们对于 setInteger() 方法有不同的实现。

package lib;
import lib.Parent;

public class C1 extends Parent{
    
    @Override
    public void setInteger(){
        i = new Integer(1);
    }
}

第二个子元素:

package lib;
import lib.Parent;

public class C2 extends Parent{
     
    @Override
    public void setInteger(){
        i = new Integer(2);
    }
}

输出是

stored entity 1
stored entity 2
stored entity 1  <-- ranged for
stored entity 2  <-- ranged for

编辑:

|-MyClass.java
|-lib
  |-Parent.java
  |-C1.java
  |-C2.java
文件结构看起来像这样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接