简体   繁体   English

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

[英]Is there a way to instantiate a child class with parent object in java?

I have a base class say 我有一个基类说

class A {
   private String name;
   private String age;

   //setters and getters for same
}

and a child class say 和一个儿童班说

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

  //setters and getters for same
}

now I've an instance of A and besides this I have to set the fields in B as well, so code would be like, 现在我有一个A的实例,除此之外我还要在B中设置字段,所以代码就像,

A instanceOfA = gotAFromSomewhere();
B instanceOfB = constructBFrom(instanceOfA);
instanceOfB.setPhone(getPhoneFromSomewhere());
instanceOfB.setAddress(getAddressFromSomewhere());

can I instantiate B with given A, but I don't want to do this way , 我可以用给定的A实例化B,但我不想这样做

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

  return B;
}

rather what I'd love to have some utility with function which is generic enough to construct object as in, 相反,我喜欢有一些功能,它具有通用性,足以构造对象,如

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;
   }
}

so that I can use it as, 所以我可以用它,

B constructBFrom(A instanceOfA) {
   return SomeUtility.constructFrom(instanceOfA, B.class);
}

Moreover, use case will not be only limited to parent-child classes, rather this utility function can be used for adapter use cases. 而且,用例不仅限于父子类,而是这个实用函数可以用于适配器用例。

PS- A and B are third party classes I've to use these classes only so I can't do any modifications in A and B. PS-A和B是我要使用这些类的第三方类,所以我不能在A和B中做任何修改。

The good practice is to have a factory class which "produces" the instances of B . 好的做法是建立一个“生产” B实例的工厂类。

public class BFactory {
    public B createBFromA(A a) { ... }
}

You have to write the code of the factory method as there is no standard way of creating a child class based on its parent class. 必须编写工厂方法的代码,因为没有基于其父类创建子类的标准方法。 It's always specific and depends on the logic of your classes. 它总是具体的,取决于你的类的逻辑。

However, consider if it is really what you need. 但是,请考虑它是否真的符合您的需求。 There are not many smart use cases for instantiating a class based on the instance of its parent. 根据其父实例实例化类的智能用例并不多 One good example is ArrayList(Collection c) - constructs a specific list ("child") containing the elements of the generic collection ("base"). 一个很好的例子是ArrayList(Collection c) - 构造一个包含泛型集合(“base”)元素的特定列表(“child”)。

Actually, for many situation there is a pattern to avoid such strange constructs. 事实上,对于许多情况避免这种奇特的结构模式。 I am aware it's probably not applicable to your specific case as you wrote that your Base and Child are 3rd party classes. 我知道它可能不适用于您的具体案例,因为您写道您的Base和Child是第三方课程。 However your question title was generic enough so I think you may find the following useful. 但是你的问题标题很通用,所以我认为你可能会发现以下内容很有用。

  1. Create an interface IBase 创建一个IBase接口
  2. Let the class Base implement the interface 让类Base实现接口
  3. Use composition instead of inheritance - let Child use Base instead of inheriting it 使用组合而不是继承 - 让Child 使用 Base而不是继承它
  4. Let Child implement IBase and delegate all the methods from IBase to the instance of Base Child实现IBase并将所有方法从IBase委托给Base实例

Your code will look like this: 您的代码将如下所示:

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();
    }
}

After you edited your question, I doubt even stronger that what you want is good. 在你编辑了你的问题之后,我更加怀疑你想要的是什么是好的。 Your question looks more like an attempt of a hack, of violating (or not understanding) the principles of class-based object oriented concept. 你的问题看起来更像是一种破坏,违反(或不理解) 基于类的面向对象概念的原则。 Sounds to me like someone coming from the JavaScript word and trying to keep the JavaScript programming style and just use a different syntax of Java, instead of adopting a different language philosophy. 对我来说听起来像是来自JavaScript的人,并试图保持JavaScript编程风格,只是使用不同的Java语法,而不是采用不同的语言哲学。

Fun-fact: Instantiating a child object with parent object is possible in prototype-based languages , see the example in JavaScript 1.8.5: 有趣的事实:在基于原型的语言中可以使用父对象实例化子对象,请参阅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

In my opinion the way you want to avoid is very appropriate. 在我看来,你想避免的方式非常合适。 There must be a piece of such code somewhere. 某处必须有一段这样的代码。

If you can't put that method in the target class just put it somewhere else (some factory). 如果您不能将该方法放在目标类中,只需将其放在其他地方(某些工厂)。 You should additionaly make your method static . 你应该另外使你的方法static

Take a look at Factory method pattern . 看看Factory方法模式

2nd option would be extending B and place this method as factory static method in that new class. 第二个选项是扩展B并将此方法作为工厂静态方法放在该新类中。 But this solution seems to be more complicated for me. 但这个解决方案对我来说似乎更复杂。 Then you could call NewB.fromA(A) . 然后你可以调用NewB.fromA(A) You should be able then use your NewB instead of B then. 然后你应该可以使用你的NewB而不是B.

You could do it via reflection: 你可以通过反思来做到这一点:

public static void copyFields(Object source, Object target) {
        Field[] fieldsSource = source.getClass().getFields();
        Field[] fieldsTarget = target.getClass().getFields();

        for (Field fieldTarget : fieldsTarget)
        {
            for (Field fieldSource : fieldsSource)
            {
                if (fieldTarget.getName().equals(fieldSource.getName()))
                {
                    try
                    {
                        fieldTarget.set(target, fieldSource.get(source));
                    }
                    catch (SecurityException e)
                    {
                    }
                    catch (IllegalArgumentException e)
                    {
                    }
                    catch (IllegalAccessException e)
                    {
                    }
                    break;
                }
            }
        }
    }

*Above code copied from online tutorial *以上代码从在线教程复制

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使Java父类方法返回子类对象的方法 - Way to make Java parent class method return object of child class Java:声明为父类,但实例化为Child,然后在Child中使用唯一方法 - Java: Declare as a parent class, but instantiate as Child, then using the unique method in Child 我可以在Java中从父实例化相同子类型的类吗? - Could I instantiate class of the same child type from parent in Java? 子实例从父类实例化 - Child Instantiate from parent class Java - 比较父类对象上的子属性 - Java - Compare child property on Parent Class Object 有没有办法从java中的子类对象调用父类方法而不修改方法 - is there any way to call parent class method from child class object in java without modifying methods Java:如何在不使用父构造函数的情况下从子对象实例化父对象? - Java: How can I instantiate a parent object from child without using parent constructor? 有什么方法可以实例化一个类 <C<A,B> &gt; Java中的对象? - Is there any way to instantiate a Class<C<A,B>> object in java? 使用父级配置或“将父级降级到子级”实例化子对象 - Instantiate Child Object with Parent config or 'downcast parent to child' 抽象类方法 - 实例化子类对象? - Abstract class method - To instantiate child class object?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM