2016-03-27 27 views
0

我有一個父類「bankAccount」與兩個子類,然後這些子類派生到其他子類。我想創建一個孫子對象並將它保存在一個List中,然後能夠與孫子們的方法進行交互。但是我似乎無法訪問這些類的方法。我所能做的只是與祖父母班的方法互動。如何訪問列表中的子類的方法?

這就是我向列表添加子類的方法。

List<bankAccount> accounts = new List<bankAccount>(); 
accounts.Add(new VistaAccount(nAccount,pass,nameClient,balance,interest)); 
+0

發佈類聲明的代碼。方法是公開的嗎? –

+0

是的,每個類的構造函數和方法都是公共的。 –

回答

2

首先,明白爲什麼C#不會讓您在銀行賬戶列表中執行此操作。

如果您有各種銀行賬戶,那麼無論你做的列表中的任何人需要適用於他們中的每一個。你不能在一個對象上調用一個方法,除非該對象保證有該方法。靜態類型系統是儘可能早地提醒你的。

話雖這麼說,如果你真的知道你只有銀行賬戶種類屈指可數,你也許可以單獨列舉出來:

foreach(var account in accounts.OfType<VistaAccount>()) 
{ 
    // call methods specific to "Vista" accounts 
} 

foreach(var account in accounts.OfType<OtherAccount>()) 
{ 
    // call methods specific to "Other" accounts 
} 

現在記住,這種方法並不能很好地擴展在長期。如果將來引入更多亞型,您可能需要回到那個位置並添加更多特殊情況。

如果您想要在每個帳戶上執行特定的操作,並且該操作的詳細信息因每種帳戶類型而異,則有更好的方法來執行此操作。只需用你的基地的銀行帳戶類型聲明一個抽象方法:

public abstract void Operation(); 

然後實現(override)這種方法在每個帳戶的種類,具體到那種指令。

  • 從長遠來看,這可以很好地擴展,因爲您不必在每次引入更多賬戶類型時都引入特殊情況。還有一件事是爲未來的自己或代碼的未來維護者記錄。
  • 它更方便,因爲如果你忘記指定子類型的操作,你會在編譯時得到一個好消息。所以如果你忘記這麼做的話,那就有一個很好的安全網。
  • 因爲現在每種銀行賬戶都支持該操作,所以編譯器會很樂意讓您在銀行賬戶列表中撥打電話。您不需要我最初提出的手動類型檢查。
+1

我故意沒有解釋投射或反射,因爲它的問題非常像嘗試做錯誤的事情,因爲錯誤的原因,但我想這樣做的方式不存在,現在沒有理由,所以... +1 – Kris

1

您無法通過父級的api訪問子級的成員。你需要引用一個暴露成員的類型,或者通過強制轉換(這通常是壞/醜),或者通過定義一個引用來作爲子類型的開始。

如果你確實需要一個子對象列表,爲什麼你要使用父母列表?如果不是更多,您需要重新考慮當前方法的設計。

2

簡單地說:你想要的東西不能完成,實際上是錯誤的。

高級:你想要什麼都可以用反射或者鑄造完成但是仍然是很不對錯誤。

您只能使用list<BankAccount>中的項目中聲明的方法(BankAccount)。如果你需要你的孫子對象行爲不同,你應該在孫子類中覆蓋方法(你的BankAccount類中必須是虛擬的)。

1

這涉及到Liskov Substitution Principle。你有一堆對象 - 有些可能是VistaAccount,其他類型的,但它們都從bankAccount繼承。通過將它們放在List<bankAccount>中,您將它們全部作爲基類bankAccount進行投射。

在這種情況下,重點是您將它們全部視爲bankAccount,根本不管它們是否爲VistaAccount或其他某種類型。唯一重要的類型是bankAccount,而子類不重要。

如果您正在檢查這些單個實例以查看它們的真實類型,那麼可能是因爲某些錯誤。如果您必須檢查每個對象以查看其類型,那麼目的就會被擊敗。根據其邏輯結論,它可能只是一個List<object>

你想要什麼(如果可能的話)是一個設計,你在每個類上調用的方法是相同的,只有這些方法的行爲是不同的。例如,Circle,SquareTriangle可以各自從Shape繼承,並且每一個覆蓋Draw()方法。該方法對於每個班級都是不同的。但是,如果你把它們全部放在List<Shape>中,那麼你可以在每個方法上調用Draw()方法,而不知道每個方法是哪個子類。

相關問題