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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24616381/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 13:30:06  来源:igfitidea点击:

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

javainheritanceinstantiation

提问by shelly

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 进行任何修改。

回答by Honza Zidek

The good practice is to have a factoryclass which "produces" the instances of B.

好的做法是有一个工厂类“生产”的实例B

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

You have towrite 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 reallywhat you need. There are not manysmart use cases for instantiating a class based on the instance of its parent. One good example is ArrayList(Collection c)- constructs a specificlist ("child") containing the elements of the genericcollection ("base").

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

Actually, for many situation there isa 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. However your question title was generic enough so I think you may find the following useful.

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

  1. Create an interface IBase
  2. Let the class Baseimplement the interface
  3. Use composition instead of inheritance- let ChilduseBaseinstead of inheriting it
  4. Let Childimplement IBaseand delegate all the methods from IBaseto the instance of Base
  1. 创建接口 IBase
  2. 让类Base实现接口
  3. 使用组合而不是继承- 让Child使用Base而不是继承它
  4. 让我们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-basedobject 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

回答by damienix

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.

看看工厂方法模式

2nd optionwould be extending B and place this method as factory static method in that new class. But this solution seems to be more complicated for me. Then you could call NewB.fromA(A). You should be able then use your NewB instead of B then.

第二个选项是扩展 B 并将此方法作为该新类中的工厂静态方法。但是这个解决方案对我来说似乎更复杂。那你就可以打电话了NewB.fromA(A)。然后你应该可以使用你的 NewB 而不是 B 。

回答by AllDayAmazing

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

*以上代码复制自在线教程