2017-10-19 10 views
0

Dでは、親クラス内から子(継承)クラスを参照できますか?親クラス内の子クラスを参照するテンプレート

私はこのような何か試してみました:typeof(this)ではなく、親クラスのメソッドをオーバーライド子クラスに解決することを望ん

abstract public @property typeof(this)[] sequence(); 

を。しかしそれはしません。それを行う方法はありますか?

ありがとうございます。あなたがtemplate this parametersを探しているよう

+0

あなたは子クラスの束、および基底クラスの種類とそれらのすべてを含むリストを持っている場合は、 'sequence'は、各要素のために戻りますか?それぞれ異なるタイプですか?それは静的なタイピングの仕組みではありません。あなたは、標準的な多形性の手段を使って、あなたが望むものを得ることができるかもしれません。 実際に何をしたいですか? – weltensturm

+0

まあ、これはまさに私が何をしたいのかではなく、説明のために、それが動作します: は、私はXMLElementのとJSONElementが継承するSerializedElementのような抽象クラスを、欲しいと言います。私はそれぞれの子クラスに、同じクラスの子要素を返すためのメソッド/プロパティを持たせたいと思います。私は(これが可能であれば)どのような型の配列(XMLElementまたはJSONElement)を返すSerializedElementに抽象メソッドを実装するのですか? –

答えて

3

は私にね。

class Base { T[] sequence(this T)() { return null; } } 
class Derived : Base {} 
static assert(is(typeof((new Derived).sequence()) == Derived[])); 

注、しかしながら、sequenceは、上記テンプレートは、基本クラスのコンテキストでインスタンス化されることも仮想関数ではない、と。ユーザーにシンプルなインターフェースを提供するには、特殊な機能に転送したいと考えています。仮想呼び出しが最も魅力的に見えるかもしれません

class Base { 
    T[] sequence(this T)() { 
     // Virtual call, requires unsafe cast of return type. 
     return cast(T[])sequenceImplVirtual(); 
     // Non-virtual call, requires safe cast of this reference 
     // and will fail if the subclass doesn't implement it correctly. 
     return (cast(T)this).sequenceImplDuck(); 
    } 
    abstract Base[] sequenceImplVirtual(); 
} 

class Derived : Base { 
    Derived[] sequenceImplDuck() { 
     return [this]; 
    } 
    override Base[] sequenceImplVirtual() { 
     return [this]; 
    } 
} 

unittest { 
    Derived[] arr = (new Derived).sequence; 
} 

:これは(あなたが関数の戻り値をキャストする必要があります。その場合には)仮想関数である、またはサブクラスでアヒル型指定された機能しますかサブクラスがsequenceImplVirtualの実装に失敗した場合、コンパイルエラーが発生します。誤って使用すると、プログラムがセグメンテーションフォールトますDerivedに由来していないBaseまたは他のクラスを返す場合はオーバーライド機能はDerived[]を返すように主張する、としないこと、しかし、注意してください。明示的なキャストは事実上これを隠す。これは分かりやすいsequenceImplVirtualが無効な値を返す場合、実行時にエラーをアサートを与える

T[] sequence(this T)() { 
    import std.algorithm.searching : all; 
    auto result = sequenceImplVirtual(); 
    assert(result.all!((Base a) => a is null || cast(T)a !is null)); 
    return cast(T[])result; 
} 

:やや冗長なプログラムはこれをテストすることができます。

一方、アヒル型指定されたソリューションは、あなたがそれを使用するまでsequenceImplDuckを実装するために忘れてしまった兆候を付与するものではありません。しかし、それは唯一の安全なキャスト(cast(T)thisを)やってに、戻り値が実際にDerived[]であることをコンパイラが保証:、-unittestしてコンパイルするとき

class Base { 
    T[] sequence(this T)() { 
     return (cast(T)this).sequenceImplDuck(); 
    } 
} 

class Derived : Base { 
    // Note: wrong return type. 
    // Will fail to compile when you call sequence(). 
    Base[] sequenceImplDuck() { 
     return [this]; 
    } 
} 

class Derived2 : Base { 
    // Note: No implementation. 
    // Will fail to compile when you call sequence(). 
} 

unittest { 
    Derived[] arr = (new Derived).sequence; 
    auto d = new Derived2; 
    auto arr2 = d.sequence; 
} 

上記は失敗しますが、あなたはユニットテストをコメントアウトした場合または-unittestなしでコンパイルすると、コンパイラは、DerivedまたはDerived2が、仮想呼び出しが必要な関数を正しく実装していないことを示すことはありません。あなたが期待するもの

関連する問題