簡體   English   中英

有沒有辦法在java中用父對象實例化子類?

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

我有一個基類說

class A {
   private String name;
   private String age;

   //setters and getters for same
}

和一個兒童班說

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

  //setters and getters for same
}

現在我有一個A的實例,除此之外我還要在B中設置字段,所以代碼就像,

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

我可以用給定的A實例化B,但我不想這樣做

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

  return B;
}

相反,我喜歡有一些功能,它具有通用性,足以構造對象,如

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

所以我可以用它,

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

而且,用例不僅限於父子類,而是這個實用函數可以用於適配器用例。

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

好的做法是建立一個“生產” B實例的工廠類。

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

必須編寫工廠方法的代碼,因為沒有基於其父類創建子類的標准方法。 它總是具體的,取決於你的類的邏輯。

但是,請考慮它是否真的符合您的需求。 根據其父實例實例化類的智能用例並不多 一個很好的例子是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();
    }
}

在你編輯了你的問題之后,我更加懷疑你想要的是什么是好的。 你的問題看起來更像是一種破壞,違反(或不理解) 基於類的面向對象概念的原則。 對我來說聽起來像是來自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

在我看來,你想避免的方式非常合適。 某處必須有一段這樣的代碼。

如果您不能將該方法放在目標類中,只需將其放在其他地方(某些工廠)。 你應該另外使你的方法static

看看Factory方法模式

第二個選項是擴展B並將此方法作為工廠靜態方法放在該新類中。 但這個解決方案對我來說似乎更復雜。 然后你可以調用NewB.fromA(A) 然后你應該可以使用你的NewB而不是B.

你可以通過反思來做到這一點:

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

*以上代碼從在線教程復制

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM