我有以下课程:
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
子对象创建Derived
类型的对象?事实上,我只想创建Base
类型的Derived
子对象的副本。
答案 0 :(得分:22)
子类中重写方法的重点在于子类的方法将在运行时执行,即使编译时类型是超类的类型。
如果由于某种原因需要超类的实例,则应该向超类添加一个复制构造函数并使用它来创建这样的实例:
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
}
答案 1 :(得分:12)
您可以使用"Has-a" relation代替"is-a" relation。
在这种情况下,您可以使其具有Derived
类型的字段,而不是Base
扩展Base
。
Derived
将是一个单独的类,具有自己的功能,并将通过其Base
字段支持Base
的功能。
如果它是正确的设计是否真的依赖于实现,并且根据提供的信息很难建议它是否正确。
答案 2 :(得分:5)
当你在Java中从另一个类继承一个类时,对于子类的对象,没有父类“子对象”这样的东西。您似乎希望基于原型的继承,就像在JavaScript中一样。
如果您想访问“子对象”,您可能希望以另一种方式实现“继承”。 Derived对象不应该从Base对象继承,而是包装它。
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();
// ...
}
答案 3 :(得分:5)
基本思想是,当创建子类的对象时,子类对象中没有基类对象的重写方法的定义,所以你永远不会从子类对象中获得这样的超级方法。
你可以通过强制转换来获得休息成员。
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;
}
注意:这是不可能从父类的重写方法 子类对象。
答案 4 :(得分:4)
如果您真的想要实现基类的实现,可以这样做:
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
}
}
关于它的重点是,如果一个类决定覆盖一个继承的方法,它还控制它自己的实例是否原始方法可用于其他类。
Derived
类始终可以通过Base
为this
实例调用super.getStr()
的原始实现,但是为了在任意实例上调用它(例如通过的那些实例)在as参数中)或者将这种可能性暴露给其他类,你需要另一种方法,如上例所示。然后,您可以在getBaseStr()
的任意实例上调用Derived
。
答案 5 :(得分:3)
你不能这样做。
派生的对象实例将永远附加到自己的类。你不能只是"还原"它回到基类,你不能只是"跳过"它被重写的方法回到基类'实施
答案 6 :(得分:3)
如果您想假设Base
和Derived
个对象共享一个共同特征,您可以实现一个接口
public interface IStr {
String getStr();
}
public class Base implements IStr {
//...
}
public class Derived implements IStr {
//...
}
public void makeStr(IStr o) {
// ...
}
如果你想复制对象我将使用@Eran回答 - 创建一个复制构造函数。
答案 7 :(得分:3)
事实上,我只想创建Derived类型的Base子对象的副本。
做吧。在Base中实现copy constructot
public Base(Base b) {
// assign all required fields from the old object
...
}
并在想要从Derived获得Base时调用它:
Base b = new Base(d);