有没有办法在java中用父对象实例化子类?

she*_*lly 5 java inheritance instantiation

我有一个基类说

class A {
   private String name;
   private String age;

   //setters and getters for same
}
Run Code Online (Sandbox Code Playgroud)

和一个儿童班说

class B extends A {
 private String phone;
 private String address;

  //setters and getters for same
}
Run Code Online (Sandbox Code Playgroud)

现在我有一个A的实例,除此之外我还要在B中设置字段,所以代码就像,

A instanceOfA = gotAFromSomewhere();
B instanceOfB = constructBFrom(instanceOfA);
instanceOfB.setPhone(getPhoneFromSomewhere());
instanceOfB.setAddress(getAddressFromSomewhere());
Run Code Online (Sandbox Code Playgroud)

我可以用给定的A实例化B,但我不想这样做,

B constructBFrom(A instanceOfA) {
  final B instanceOfB = new B();
  instanceOfB.setName(instanceOfA.getName());
  instanceOfB.setPhone(instanceOfA.getAge());

  return B;
}
Run Code Online (Sandbox Code Playgroud)

相反,我喜欢有一些功能,它具有通用性,足以构造对象,如

public class SomeUtility {

   public static <T1, T2> T2 constructFrom(T1 instanceOfT1, Class<T2> className) {

      T2 instatnceOfT2 = null;

      try {
         instatnceOfT2 = className.newInstance();
         /*
         * Identifies the fields in instanceOfT1 which has same name in T2
         * and sets only these fields and leaves the other fields as it is.
         */
      } catch (InstantiationException | IllegalAccessException e) {
         // handle exception
      }          

      return instatnceOfT2;
   }
}
Run Code Online (Sandbox Code Playgroud)

所以我可以用它,

B constructBFrom(A instanceOfA) {
   return SomeUtility.constructFrom(instanceOfA, B.class);
}
Run Code Online (Sandbox Code Playgroud)

而且,用例不仅限于父子类,而是这个实用函数可以用于适配器用例.

PS-A和B是我要使用这些类的第三方类,所以我不能在A和B中做任何修改.

Hon*_*dek 11

好的做法是建立一个"生产"实例的工厂B.

public class BFactory {
    public B createBFromA(A a) { ... }
}
Run Code Online (Sandbox Code Playgroud)

必须编写工厂方法的代码,因为没有基于其父类创建子类的标准方法.它总是具体的,取决于你的类的逻辑.

但是,请考虑它是否真的符合您的需求.有没有很多聪明的用例实例根据其父的实例类.一个很好的例子是ArrayList(Collection c) - 构造一个包含泛型集合("base")元素的特定列表("child ").

事实上,对于许多情况有就是避免这种奇特的结构模式.我知道它可能不适用于您的具体案例,因为您写道您的Base和Child是第三方课程.但是你的问题标题是通用的,所以我认为你可能会发现以下内容很有用.

  1. 创建一个界面 IBase
  2. 让类Base实现接口
  3. 使用组合而不是继承 - 让我们Child 使用 Base而不是继承它
  4. 让我们Child实现IBase并将所有方法委托IBase给实例Base

您的代码将如下所示:

public interface IBase {
    String getName();
    int getAge();
}

public class Base implements IBase {
    private String name;
    private int age;
    // getters implementing IBase
}

public class Child implements IBase {
    // composition:
    final private IBase base;        
    public Child(IBase base) {
        this.base = base;
    }
    // delegation:
    public String getName() {
        return base.getName();
    }
    public int getAge() {
        return base.getAge();
    }
}
Run Code Online (Sandbox Code Playgroud)

在你编辑了你的问题后,我更加怀疑你想要的是什么是好的.你的问题看起来更像是一种破坏,违反(或不理解)基于类的面向对象概念的原则.对我来说听起来像是来自JavaScript的人,并试图保持JavaScript编程风格,只是使用不同的Java语法,而不是采用不同的语言哲学.

有趣的事实:在基于原型的语言中可以使用父对象实例化子对象,请参阅JavaScript 1.8.5中的示例:

var base = {one: 1, two: 2};
var child = Object.create(base);
child.three = 3;

child.one;   // 1
child.two;   // 2
child.three; // 3
Run Code Online (Sandbox Code Playgroud)

  • 这假设OP的所需构造首先是一个好主意...... (3认同)