Java 从派生类创建基类对象

Java 从派生类创建基类对象,java,class,inheritance,Java,Class,Inheritance,我有以下课程: public class Base{ //fields public String getStr(){ String str = null; //Getting str from the fields return str; } } public class Derived extends Base{ //fields //some other fileds public Str

我有以下课程:

public class Base{

    //fields
    public String getStr(){
        String str = null;
        //Getting str from the fields
        return str;
    }
}

public class Derived extends Base{

    //fields
    //some other fileds
    public String getStr(){
        String str = null;
        //Getting str from the fields + some other fields
        return str;
    }
}
现在,我有了一个方法,它有一个类型为
Derived
的参数

public void makeStr(Derived d){
    Base b = null;
    //Getting the Base class subobject from d and printing the str
}
但我不能只做
b=d
然后调用
b.getStr()
,因为将调用方法
d.getStr()


如何从派生的
类型的对象的
Base
子对象创建
Base
类型的对象?事实上,我只是想创建类型
派生的

Base
子对象的副本。重写子类中的方法的要点是,子类的方法将在运行时执行,即使编译时类型是超类的

public void makeStr(Derived d){
    Base b = null;
    //Getting the Base class subobject from d and printing the str
}
如果出于某种原因需要该超类的实例,则应向该超类添加一个复制构造函数,并使用该构造函数创建此类实例:

public class Base {
    ...
    Base (Base source) {
        // copy the properties from source
    }

}
然后:

public void makeStr(Derived d)
{ 
    Base b = new Base(d);
    ... b.getStr() will call the Base class implementation
}
你不能这样做


派生对象实例将永远附加到它自己的类。您不能只是将其“还原”回基类,也不能只是“跳过”其重写的方法以返回基类的实现。

如果您想假定
基类和
派生的
对象共享一个公共特性,您可以实现一个接口

public interface IStr {
    String getStr();
}
public class Base implements IStr {
    //...
}
public class Derived implements IStr {
    //...
}
public void makeStr(IStr o) {
    // ...
}
如果你想复制对象,我会选择@Eran answer-创建一个复制构造函数。

你可以使用一个而不是

在这种情况下,您可以使其具有类型为
Base
的字段,而不是
Derived
extend
Base

Derived
将是一个单独的类,具有自己的功能,并通过其
Base
字段支持
Base
的功能

根据提供的信息,设计是否正确实际上取决于实现,很难判断是否正确

事实上,我只是想创建派生类型的基子对象的副本

就这么做吧。在您的基础上实现copyconstructot

public Base(Base b) {
    // assign all required fields from the old object
    ...
}
并在希望从派生的

Base b = new Base(d);

当您在Java中从另一个类继承一个类时,子类的对象没有父“子对象”这样的东西。您似乎希望使用基于原型的继承,就像在JavaScript中一样

如果您希望访问“子对象”,您可能希望以另一种方式实现“继承”。派生对象不应从基础对象继承,而是将其包裹

class Derived {

    private Base base;

    public Derived(Base base) {
        this.base = base;
    }

    public Base getBase() {
        return this.base;
    }
}

public void makeStr(Derived d){
    Base b = d.getBase();
    // ...
}

基本思想是,当创建子类的对象时,子类对象中没有基类对象的重写方法的定义,所以您永远不会从子类对象中得到这样的超方法

您只需键入它,就可以获得rest成员

Base castedInBase = derivedObj;
//child class specific member as well as hided fields are also availble here.
使用构造函数只能获取父类的对象-

Base base= new Base(derivedObj);
//orrided method of base class lost,will refer to super class overrided method.
假设下面是你的方法-

public void makeStr(Derived derivedObj){
        Base castedInBase = derivedObj;
    }
注意:这不可能从中获取父类的重写方法 子类对象


如果您真的想让基类的实现可用,您可以这样做:

public class Derived extends Base{
    …
    public String getStr(){
        String str = null;
        // produce the specialized string
        return str;
    }
    public String getBaseStr(){
         return super.getStr(); // delegate to base class
    }
}
关键是,如果一个类决定重写一个继承的方法,它还可以为自己的实例控制原始方法是否对其他类可用


派生的
类始终可以通过
super.getStr()
实例调用
的原始实现,但为了在任意实例(例如作为参数传入的实例)上调用它,或将这种可能性公开给其他类,您需要另一种方法,如上面的示例中所示。然后您可以对
派生的
的任意实例调用
getBaseStr()

str
不是字段,而是方法变量。@amit和?我们从字段中创建str。我认为创建该字符串的细节(比如在字段上调用toString()方法)在这里并不重要。我误解了你的意图,尽管你把
str
称为字段,但它本身就是这个
派生的
扩展的
,或者你的代码就是这样?@dubey theHarcourtians当然是这样。是否有一种通用的方法来创建这样的对象,即基本子对象的副本?我的意思是避免手动处理字段。@St.Antario您可以通过反射来完成。我的意思是我们已经在派生对象中有了基本子对象。为什么我们必须在构造函数中显式地复制属性?如果没有反射,就不可能做到这一点。@St.Antario它可能有更多字段。@St.Antario如果希望调用基本实现,为什么要重写该方法?如果将该方法声明为final,则可以防止重写该方法,在这种情况下,将始终调用基本实现!在很多情况下,人们应该使用组合而不是继承!!!-有时人们只是使用继承,因为在学校里学习了,并且认为要做正确的OO,你必须有很多扩展和实现,因为它看起来很有意思。实际上,“拷贝子对象”概念OP在谈论似乎是直接从C++中得到的,并且几乎没有任何其他语言有意义。
public void makeStr(Derived d){
    Base b = null;
    //Getting the Base class subobject from d and printing the str
}