2011-08-30 63 views
2

我正在設計一個框架,並在這個過程中遇到了一個有趣但很可能的基本問題。我有一個名爲的基類CoreEngine和其他兩個擴展它的類:CoreEngine1CoreEngine2。我創建了一個接口,每個類都會實現這個接口,以增加項目的靈活性。但是,我遇到了一個問題...接口中我的方法的定義與每個繼承類中的定義不匹配!每個類必須實現以下方法:OOP正確使用AS3中的接口

function get avatar():AvatarBase;

的問題是,CoreEngine1CoreEngine2期待一個不同類型的化身:

CoreEngine1

功能得到頭像():AvatarScaling

CoreEngine2

函數來獲取頭像():AvatarPlatform

正如你所看到的,在CoreEngine1和CoreEngine2 化身返回類型還不至於在接口中指定匹配類型。我希望既然AvatarScaling和AvatarPlatform都繼承了AvatarBase我不會遇到編譯問題。然而,這種情況並非如此。根據Adobe的文檔,類型必須與接口匹配。我試圖遵循面向對象編程的核心概念之一來擴展我的框架的靈活性:「編程到接口而不是實現」。我想到的第一件事是訪問器方法的返回類型應該是一個接口類型(也許我只是回答了我自己的問題)。

我確定這是其他人遇到過的常見問題。在架構上,您認爲解決此問題的最佳方法是什麼?提前致謝!

問候,

回答

0

我想你回答了你自己的問題...返回類型仍然是AvatarBase,您需要按照您在界面中指定的簽名...但你可以在技術上返回該函數中的任何後代AvatarBase。因此,在CoreEngine1中做類似

return new AvatarScaling(); 

將是完全可以接受的。

當然,在您的調用函數中,您將獲得一個AvatarBase實例,並且您必須知道這是爲了投射到特定的子類。

CoreEngine1 ce1 = new CoreEngine1(); 
AvatarScaling avatar = ce1.avatar() as AvatarScaling; 
+2

該代碼是不是AS3,你的意思是'無功CE1 :CoreEngine = new CoreEngine1(); var作爲:AvaterScaling = ce1.avatar()作爲AvatarScaling或者(AvatarScaling)(ce1.avatar())或者AvatarScaling(ce1.avatar());'。 – Taurayi

+0

謝謝你的迴應。這很清楚並且合理。 –

1

這是接口如何工作和聲明的限制。

如果在返回類型中可能會發生繼承,就像您在AvatarBase和子類中所描述的那樣,那麼我認爲正確的做法是使返回類型成爲最小公分母,並且只處理其他結果對象結束。所以,如果你正在處理一個CoreEngine1對象,你知道你可以將結果從AvatarBase轉換爲AvatarScaling。或者,如果您不知道要調用的對象類型get avatar(),則可以鍵入檢查返回的值。只有在您打算調用AvatarScaling上存在的方法但不在AvatarBase上的方法時才需要進行類型檢查。我不認爲在這種情況下返回接口類型會給你帶來太多的收益,因爲接口可以實現的唯一事情就是所有形式的Avatar分享,這與AvatarBase中的方法沒有什麼不同。

+0

同意。我確保保持基本類型,並在必要時進行類型轉換。我的希望是,如果我在* CoreEngine2 *裏面聲明頭像爲類型** AvatarPlatform **,那麼我可以返回該類型而不必將其拋棄。但看起來這是使用正確的方法。感謝您的反饋。 –

1

和HotN和Dinko一樣,最好允許get avatar()返回AvatarBase allways,然後將返回的對象作爲具體的子類。

使用丁科的例子:

public /* abstract */ class CoreEngine 
{ 
    public /* abstract */ function get avatar():AvatarBase {} 
} 

public function CoreEngine1 extends CoreEngine 
{ 
    override public function get avatar():AvatarBase { return new AvatarScaling(); } 
} 

public function CoreEngine2 extends CoreEngine 
{ 
    override public function get avatar():AvatarBase { return new AvatarPlatform(); } 
} 

public /* abstract */ class AvatarBase {} 

public class AvatarScaling extends AvatarBase 
{ 
    public function someAvatarScalingMethod():void {} 
} 

public class AvatarPlatform extends AvatarBase 
{ 
    public function someAvatarPlatformMethod():void {} 
} 

要使用從AvatarScaling的方法,將返回的對象:

var c1:CoreEngine1 = new CoreEngine1(); 
var avatarScaling:AvatarScaling = AvatarScaling(c1.avatar()); 
avatarScaling.someAvatarScalingMethod(); 

心連心

+0

謝謝你的迴應。看起來我將不得不使用類型轉換方法。 –

+0

這就是你應該做的,非常多。 – recursivity