2012-01-23 11 views
2

おはようございます。配列内の抽象クラスの派生クラス

基本抽象クラスの派生クラスを作成して使用する方法について質問があります。

どのように動作するのかよくわかりません。

私の目標:そこにあるべき機能かを定義し、別の派生クラスを作成します基本的なクラスを作成します。次に、基底クラスの配列を作成し、異なる派生クラスをインスタンス化します。例えば

abstract class UIElement 
{ 
    //constructor 
    abstract public UIElement(); 
    //draw element 
    abstract public void Draw(int mouseX, int mouseY); 
    //checks if the element is pointed at by mouse 
    abstract public Boolean IsPointed(int mouseX, int mouseY); 
    //defines what happens when clicked 
    abstract public void Click(int mouseX, int mouseY); 
    //destructor 
    abstract public ~UIElement(); 
} 

その後、いくつかの派生クラスを作成し、そのように実行します。

UIElement[] qwe = new UIElement[3]; 
qwe[0] = new UIElementButton(); 
qwe[1] = new UIElementLabel(); 
qwe[2] = new UIElementSomethingElse(); 

1)私は決定的なを見つけることができないので、それを行うための適切な方法は何ですか基底クラスまたは派生:彼らは宣言されなければならないクラス変数、について答えたり、それを説明するだろう記事...

2)?

3)異なる派生クラスに異なる変数がある場合、どのように対処する必要がありますか?

4)派生クラスは異なる引数を含む異なるコンストラクタを持つことができますか?以下のコメントで

+0

本当にはっきりしていますが、本当に正しいことは正しいですか。 – kkm

+0

それは何が問題なのですか?あなたのコードは正しいようです。私が指摘する唯一のことは、抽象的なデストラクタにはほとんど使用されないことです。代わりに 'IDisposable'を実装してください。 –

+0

@kkm、決して少なくはありません:) – NewProger

答えて

6

questionnerは、ビューの一般的なベストプラクティスと正確性の点からは、抽象クラス

と継承のhierachiesはを書くためのベストプラクティスに関するアドバイスを探している、あなたはあなたのUIElementベースを宣言するべきですコンストラクタ上の抽象クラスを持たず、ファイナライザを持たないクラスです。例えば

public class UIElementButton : UIElement 
{ 
    // Optional - create parameterless constructor and 
    // explicitly call base constructor 
    public UIElementButton() : base() 
    { 
    } 

    // Mandatory - must override abstract methods 
    public override Draw(int mouseX, int mouseY) 
    { 
    } 

    // Mandatory - must override abstract methods 
    public override Boolean IsPointed(int mouseX, int mouseY) 
    { 
    } 

    // Mandatory - must override abstract methods 
    public override void Click(int mouseX, int mouseY) 
    { 
    } 
} 

を次のようにあなたは、あなたはあなたが上記のとおりに派生クラスを定義する場合は、あなたのように基本型の配列の要素と店をインスタンス化することができることを正しい派生クラスを実装することができ

public abstract class UIElement 
{ 
    //constructor 
    protected UIElement(); 
    //draw element 
    public abstract void Draw(int mouseX, int mouseY); 
    //checks if the element is pointed at by mouse 
    public abstract bool IsPointed(int mouseX, int mouseY); 
    //defines what happens when clicked 
    public abstract void Click(int mouseX, int mouseY); 
} 

次のようになります:

UIElement[] qwe = new UIElement[3]; 
qwe[0] = new UIElementButton(); 
qwe[1] = new UIElementLabel(); 
qwe[2] = new UIElementSomethingElse(); 

qwe[0].Click(1, 2); // Invokes UIElementButton.Click 
qwe[1].Draw(3, 4); // Invokes UIElementLabel.Draw 

また、WPFで定義されたUIElementクラスがあることにも注意してください。あなたの型に名前空間を定義する場合、これは問題ではありませんが、カスタム型を区別するために、より明示的な型名、例えばBaseElementを考えてみてください。コメント欄に、クエリについて


抽象クラスの使用方法の更なるアドバイスについて、All about abstract classes - Codeprojectを参照してください。 - クラス変数は宣言する必要があります:基本クラスまたは派生クラス? - 異なる派生クラスに異なる変数がある場合、どう対処する必要がありますか? - 派生クラスは異なる引数を含む異なるコンストラクタを持つことができますか?

  1. クラス変数は、それらが必要とされる範囲内で宣言する必要があります。

    これらは、しかし、スターターとして、私が言うことができ、本当にさまざまな質問やGoogleで自分の研究のためのテーマです。意味は、変数Guid _uiElementIdがあり、それが派生型によってアクセスされたい場合、それは基本クラスで宣言され、protectedとしてマークされるべきです。あなたが持っている場合はUIElementButton内の変数はPoint _mousePointと呼ばれ、唯一のUIElementボタンは大丈夫ですprivate

  2. としてそこマークでそれを残して、それを必要とする - 基底クラスから独自のプライベート変数および保護された変数を参照することができ、あらゆるタイプ。名前が衝突しないようにしてください。

  3. はい、可能です。


public class UIElementButton : UIElement  
{  
    private string _buttonText; 

    // Overloaded ctor 
    public UIElementButton(string buttonText) : base() 
    { 
     buttonText = buttonText; 
    } 

    // Default constructor. Mark as private or protected 
    // to hide from external API 
    public UIElementButton() : base() 
    { 
    } 
} 

敬具、

+0

詳細な説明をいただきありがとうございます。私はそれがどのように動作するかを勉強しようとしたとき、私はいくつかのポイントを逃したようだあなたの答えのおかげで今私は理解しているようです:)私は今実装しようとします。 – NewProger

+0

@NewProgerうれしい私は助けになるかもしれない。将来的には、あなたが本当に必要としていることを推測しなければならないので、質問をより明確に説明してください。幸いにも私は幸運な推測をしました!私が助けることができる他に何かありますか?コメントに投稿してください。よろしくご連絡ください –

+0

できるだけクラス変数について宣言する必要があります:基本クラスまたは派生した答えの情報に含めることができますか?異なる派生クラスに異なる変数がある場合、どのように対処する必要がありますか? 2番目の質問は、異なる引数を含む異なるコンストラクタを持つ派生クラスですか? あなたの時間をすごして申し訳ありません...しかし、私は少なくともあなたの答えを選択し、それを "アップ"するようにします。 – NewProger

0

これが問題ですが、あなたのコードがコンパイルされませんことをご質問から明らかではありません。 C#では、abstractコンストラクタを持つことはできません。ファイナライザはpublicでもabstractでも構いません。それらのいずれかを持つ必要はありません、あなたは単にそれらを削除することができます。

おそらく、管理されていないリソースを破棄しない限り、通常はファイナライザを使用しないでください。それが必要な場合は、IDisposableも実装したいと考えています。

3

私が正しく推測するならば、OPはC++バックグラウンドから来ています。 C++とC#の間には多くの類似点がありますが、すべての機能が1:1に一致するわけではありません。

あなただけセットアップするすべての子孫のための有効な操作をあなたの「基本クラス」をしたい場合、それはコードを持っていない、つまり、あなたがインターフェイスを使用する必要があります

public interface IUIElement 
{ 
    //draw element 
    void Draw(int mouseX, int mouseY); 
    //checks if the element is pointed at by mouse 
    bool IsPointed(int mouseX, int mouseY); 
    //defines what happens when clicked 
    void Click(int mouseX, int mouseY); 
} 

をコンストラクタの必要はありませんかデストラクタを使用したり、メソッドをpublicとして明示的に宣言することはできません。インターフェイスにはprivateメソッド/プロパティを含めることができないため、それを実装するクラスに委ねられます。

この後、あなたは(あなたのためにそれらをスタブすることができますVisual Studioの)のようなあなたのクラスを宣言することができます。

public class UIElementButton : IUIElement 
{ 
    public UIElementButton() 
    { 
    ... 
    } 

    void Draw(int mouseX, int mouseY) 
    { 
    ... 
    } 

    bool IsPointed(int mouseX, int mouseY) 
    { 
    ... 
    } 

    void Click(int mouseX, int mouseY) 
    { 
    } 
} 

(配列で)あなたのコードの残りの部分を正常に見える、しかし、私は好みますリストの代わりにリスト:

List<IUIElement> qwe = new List<IUIElement>(); 
qwe.Add(new UIElementButton()); 
qwe.Add(new UIElementLabel()); 
qwe.Add(new UIElementSomethingElse()); 

// some sample usages 
foreach(IUIElement element in qwe) 
{ 
    element.Click(); 
} 

qwe[0].Click() //invokes UIElementButton.Click(); 

//gets all pointed elements 
var pointedElements = qwe.Where(e => e.IsPointed(x,y)); 
+0

説明ありがとうございます。それは本当に助けになりました。また、いいえ、私はC++のバックグラウンドではないので、私は主にWebプログラミングをPHPでやっていません。そのような問題は発生しません。データ型の配列に何かを入れることができます。これが私の混乱の理由です。 。 とにかく、ありがとう! – NewProger

+0

+1は、たとえばを使用します。 @NewProger C#は強く型付けされているため、抽象概念と継承階層を扱うためには少し異なるパラダイムを習得しなくてはなりません –

関連する問題