2012-02-20 9 views
7

派生クラスのインスタンスを返さなければならない抽象メソッドを作成することはできますか?私はこれを行うことができます:派生クラスのインスタンスを返す抽象メソッド

abstract class Base 
{ 
    public abstract Base GetObj(); 
} 

class Derived : Base 
{ 
    public Derived() { } 

    public override Base GetObj() 
    { 
     return new Derived(); 
    } 
} 

をしかし、それは、そのようなDerived::GetObj()Derivedを返すことを余儀なくされていることを実行する方法があった場合、私は不思議でしたか?

ありがとうございました。ジェネリックを使用し

+1

参照:落とし穴と挑戦を考慮するにはhttp://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspxをご覧ください。 –

+0

リンクをありがとう。面白い読書。 – Eric

答えて

16

がこれを可能にする必要があります(導出インスタンスのすべてがデフォルトのコンストラクタを使用して作成されている場合)

abstract class Base<T> 
    where T : Base<T> 
{ 
    public abstract T GetObj(); 
} 

class Derived : Base <Derived> 
{ 
    public Derived() { } 

    public override Derived GetObj() 
    { 
     return new Derived(); 
    } 
} 

あなたも、この一層の簡素化できます。

abstract class Base<T> 
    where T : Base<T>, new() 
{ 
    public static T GetObj() 
    { 
     return new T(); 
    } 
} 

class Derived : Base<Derived> 
{ 
    public Derived() { } 
} 
+3

これは、* first *派生クラスのみを強制的に返すことに注意してください。 2番目の派生クラスは最初のクラスを返します。 –

+0

ありがとう、これは私が必要とするもののように見えます。これを静的メソッドにする方法はないと思いますか? – Eric

+0

はいメソッドは静的にすることができます。この場合、ファクトリがあります。 'Derived.GetObj()'を使うことができます。 – Lukazoid

6

は、あなたが持っているものですほぼ完全には抽象的な工場ではありません。私はまず、派生クラスの実装者に任せて、それを正しいものにするか、それとも単にそれを信じるかを言います。

もう1つの答えは、奇妙に反復するテンプレートパターンとして知られています。これは、派生型が特定の入力または出力位置でそれ自身を使用するように強制するために、型システムを使用しようとする基本クラスを持つ場所です。

public abstract class Foo<T> where T : Foo<T> 
public class Bar : Foo<Bar> 

このアイデアは他の言語でも使用できます。 C#で正しく動作するのは、これだけです。バーの上記の定義で、今も私は持つことができます

public class Baz : Foo<Bar> 

これは完全に合法です。 BarFoo<Bar>です。これは、Bazがそれを使用するために必要なすべてです。 Bazは実際にFoo<Baz>を使用する必要はありません。

C#のタイプシステムは、強制したいものを強制することはできません。このパターンがあっても、あなたは以前と同じポジションにいます。派生クラスの実装者は、それを正しく行うためには依然として信頼する必要があります。

このトピックの詳細については、this blogを参照してください。

関連する問題