簡體   English   中英

用Java將對象轉換為其子類

[英]Transform an object to its subclass in Java

這不是常規問題,請聽我解釋。

我有一個Animal類的對象。 如何將其轉換為Cat的子類? 像這樣:

Animal a = new Animal();
Cat c = (Cat) a;

當然,我知道不可能直接從Animal投射到Cat 但是我不想手動創建新的Cat並將字段從Animal復制到它。 因為有時我有很多需要轉換的類層次結構。 我該如何一般地解決呢?

忽略這個事實,在您的示例中,您想按原樣反轉關系(例如“一個蘋果是一個水果”與“一個水果是一個蘋果”)-在某種程度上毫無意義。

但是,讓我們想象一下一個案例,其中您必須使盆栽看起來像一個蘋果。 因此,您要做的是將所有果肉切掉,然后將土豆放入蘋果中(我在這里使用水果示例,因為對於動物來說,它有點混亂)。 這稱為代理或包裝。

兩種技術都可以在Java中靜態或動態地完成。

靜態地:包裝器:

  • 創建新的類,即VeggiAppleWrapper
  • 讓它擴展蘋果(所以包裹起來的東西就像蘋果一樣)
  • 定義一個接受其他類型的構造函數(例如,Potato)
  • 實現/重寫常用方法並將調用委托給包裝的對象
  • 實現所有其他拋出UnsupportedOperationException的方法

動態地:代理:

  • 您必須至少為目標類型定義一個接口(即interface Apple
  • 使用代理創建代理實例
  • 使用已實現接口列表中的Apple接口
  • 實現一個MethodInvocationHandler ,它為您執行轉發,類似於Wrapper,但使用了反射
  • 將代理投放到Apple

使用Java動態代理的替代方法是代碼生成庫,例如CGLibJavaassist ,它們在運行時生成目標類型的子類,該類與包裝程序基本相同,但實現方式類似於代理。

為了只將值從animal復制到cat實例(因為animal是超類,某些字段應該是公用的),您也可以使用反射API

for(Field f : Animal.class.getDeclaredFields()) { 
  f.setAccessible(true)
  f.set(cat, f.get(animal));
} 

這只是一個簡單的示例,沒有異常處理,也沒有考慮Animal的超類的字段( getDeclaredFields僅檢索此類的字段)。

在子類中創建一個復制構造函數呢?

public Cat(Animal animal) { super(animal); }

Animal類中聲明此類構造函數,並通過使用super(animal)從任何子類中向其傳遞控件,您將在其中定義自定義邏輯。

我想你做對了

Animal animal = new Animal();
Cat cat = new Cat();

public void foo(){
  animal = cat; //works because Animal is parent class
  cat = (Cat) animal; //you cast Animal to Cat like as parent to child
}

檢查一下https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

我希望這會有所幫助

暫無
暫無

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

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