2009-03-26 3 views
2

C#の基本クラスをいくつかの追加機能で拡張したいと考えています。私は拡張バージョンに変換する必要がある基本クラスオブジェクト(アカウント)の配列を返す既存のコードを持っています。継承の問題を頭に浮かべて

だから私は拡張版があります。

class AccountXtra : Account 
{ 
    public int Period { get; set; } 
    public int Visitors { get; set; } 
    public string ContactName { get; set; } 
} 

すべてが良いです。

アカウントのインスタンスがあるときに、AccountXtraの新しいインスタンスを作成するにはどうすればよいですか?

私が試してみました:

//This doesn't work 
AccountXtra newInstance = (AccountXtra)accountInstance; 
//This also doesn't work 
AccountXtra newInstance = new AccountXtra(); 
newInstance = accountInstance; 

答えて

1

あなたがベースを、今派生クラスの新しいオブジェクトを生成しないする必要があります。古いコールをnew Accountに置き換えて、new AccountXtraに置き換えてください。それとも、あなたはAccountオブジェクトを取り、それの新しい派生クラスのバージョンを作るAccountXtraのコンストラクタを必要とする:

public AccountXtra(Account baseInstance) : this() 
{ 
    this.Field1 = baseInstance.Field1; 
    this.Field2 = baseInstance.Field2; 
    ... 
} 

説明:あなたはそれがない限り、派生クラスに基本クラスをキャストすることはできません派生クラス型です。これは動作します:

AccountXtra accountXtra = new AccountXtra(); 
Account xtraAsBase = (Account)accountXtra; 
AccountXtra xtraCastBack = (AccountXtra)xtraCastAsBase; 

しかし、これはしません:

Account Base = new Account(); 
AccountXtra baseAsDerived = (AccountXtra)Base; //Cast base to derived class 
+0

"this.Field1 = baseInstance.Field1"これは私が避けたいものです。 代わりに、基本クラスをラップし、それをプロパティとして公開します。これはあまり悪くないようです –

+0

その場合、私は継承を全く使用しません。基本クラスのインスタンスを含む新しいクラスを作成します。しかし、Accountオブジェクトを作成するコードにアクセスできる場合は、代わりにAccountXtraオブジェクトを作成するように変更してください。その後、あなたは自由に何でもしたいです。 –

1

をしかし、私はアカウントのインスタンスを持っているとき、どのように私はAccountXtraの新しいインスタンスを作成するのですか?

これは間違った方法です。アカウントオブジェクトとしてどこでも扱うことができるAccountXtraオブジェクトを作成する必要があります。

ちなみに、リスト作成コードで作成したいオブジェクトのタイプがわからない場合は、factory patternsをお読みください。

あなたが持っている特定の問題を自由に質問を更新してください。

1

基本クラスをサブクラスに変換することはできません。つまり、オブジェクトのタイプが「アカウント」の場合、「AccountXtra」にキャストすることはできません。ただし、 "AccountXtra"クラスを持っている場合は、 "Account"から継承しているため、Accountにキャストできます。

既存のコードのソースがある場合は、「new Account()」コンストラクタを呼び出す場所を変更し、「new AccountXtra()」に変更する必要があります。また、 "Account"クラスのインスタンスを "AccountXtra"に置き換えてください。

もう1つのアイデアはAccountXtra()で "Account"型の引数をとり、すべての情報を新しいインスタンス。効率的ではありませんが、あなたが探している効果が得られます。

public class AccountXtra : Account 
{ 
    public AccountXtra(Account existingAccount) : base() 
    { 
     this.accountName = existingAccount.accountName; 
     this.accountNumber = existingAccount.accountNumber; 
     ... 
    } 
} 
+0

答えをありがとう。私は明らかに間違っていたクラス継承についての仮定を持っていました(現実ではないという意味で間違っていました!) –

+0

"スーパークラス"ではなく "サブクラス"かもしれないと思います。また、そのインスタンス。 – recursive

+0

問題ありません。これらの勘定科目を生成しているコードにアクセスできない場合は、別のオプションを試してみてください。 –

0

あなたはすべての共通の属性を持つ一般的な抽象クラスに抽象的にそれをしたいことがあります。

public abstract class Account 
{ 
    //all common members make them abstract 
    public abstract int AccountId { get; set; } 
} 

はその後持っていますあなたの余分な、新しい "基本"アカウントは、その一般的なアカウントクラスから派生していますか?

public class AccountBasic : Account 
{ 
    public override int AccountId { get; set; } 
    //implement the rest 
} 

public class AccountExtra : Account 
{ 
    public override int AccountId { get; set; } 
    //your extra details 
    public int Period { get; set; } 
    public int Visitors { get; set; } 
    public string ContactName { get; set; } 
} 

これにより、次のようなコレクションを作成できます。List allAccounts;そこでは共通の属性を操作できます。あなたの特別なクラスのインスタンスを維持しながら。

+0

これはデコレータパターンになります。このような状況では、殺すように見えます。 –

0

これはこれまでの回答のコメントとして意図されていましたが、長すぎると思います。

親クラスのインスタンスを取得し、そこからデータをコピーするコンストラクタを持つ子クラスを持つことは、かなり広範な標準です。複数のレベルの継承やその他のクラスでこれが引き起こす可能性のある頭痛を最小限にする方法の1つは、この作業を行う保護された関数を作成することです。この例ではAssignと呼んでいます。私たちには、PersonEmployee、およびManagerという3つのクラスがあるとします。彼らはそれぞれ順番にもう一方から継承します。

public class Person 
{ 
    private string name; 

    public string Name 
    { 
     get { return name; } 
     set { name = value; } 
    } 

    protected void Assign(Person otherPerson) 
    { 
     Name = otherPerson.Name; 
    } 
} 

今、私たちは、従業員を定義します。

public class Employee : Person 
{ 
    private int employeeID; 

    public Employee() { } 
    public Employee(Person newEmployee) : this() 
    { 
     base.Assign(newEmployee); 
    } 

    public int EmployeeID 
    { 
     get { return employeeID; } 
     set { employeeID = value; } 
    } 

    protected new void Assign(Employee otherEmployee) 
    { 
     base.Assign(otherEmployee); 

     EmployeeID = otherEmployee.EmployeeID; 
    } 
} 

その後、我々はマネージャーのための同じ例は次のとおり我々は変更することができるように

public class Manager : Person 
{ 
    private string department; 

    public Manager() { } 
    public Manager(Employee newManager) : this() 
    { 
     base.Assign(newManager); 
    } 

    public string Department 
    { 
     get { return department; } 
     set { department = value; } 
    } 

    protected new void Assign(Manager otherManager) 
    { 
     base.Assign(otherManager); 

     Department = otherManager.Department; 
    } 
} 

ので、各クラスのAssign()方法はnewを宣言しました継承クラスには浅いコピー機能を提供するために存在します。

このパターンは、古いオブジェクトと同じデータだけを持つNEWオブジェクトを作成することに注意してください。古いオブジェクトはまだ存在し、既存の参照は新しいオブジェクトを指しません。実際にはオブジェクトのTYPEを変更することはできません。

+0

ああ、シンプルなパターン –