2016-03-27 28 views
0

私は2つのサブクラスを持つ親クラス "bankAccount"を持っていて、それらのサブクラスは他のサブクラスに派生しています。私は孫のオブジェクトを作成してリストの中に保存し、孫のメソッドと対話できるようにしています。しかし、私はこれらのクラスのメソッドにアクセスできないようです。私ができることは、祖父母クラスのメソッドと相互作用することだけです。リスト内のサブクラスのメソッドにアクセスするには?

これは、リストにサブクラスを追加する方法です。

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

クラス宣言のコードを投稿してください。メソッドは公開されていますか? –

+0

はい、各クラスのコンストラクタとメソッドは共にpublicです。 –

答えて

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,SquareおよびTriangleは、それぞれShapeから継承することができ、それぞれがDraw()の方法を無効にすることができます。その方法はクラスごとに異なります。しかし、それらをすべてList<Shape>に入れると、それぞれのサブクラスを知らなくてもそれぞれに対してDraw()メソッドを呼び出すことができます。

関連する問題