2

次のクラスがあると考えてください。

/// File classes.d
class C {
    string type() { return "C"; };
}

class C1 : C {
    override string type() { return "C1"; };
}

class C2 : C {
    override string type() { return "C1"; };
}

次に、次のような別の場所にファクトリを実装したいと思います。

/// File factory.d
module factory;
import std.functional;
import std.stdio;

void main() {
    mixin(import("classes.d"));
    auto c = cast(typeof(mixin("C1"))) Object.factory("C1");
    writeln(c.type());
}

コンパイラ(dmd 2.058)は私にこう言っています:

factory.d(7): Error argument C1 to typeof is not an expression

私は次の行がうまくコンパイルされることを知っています:

auto c = cast(C1) Object.factory("classes.C1");

ただし、これにはコンパイル時にタイプ(C1)を知っている必要があります。実行時に型を取得したい(文字列など)。

4

2 に答える 2

5
mixin(`auto c = cast(typeof(C1)) Object.factory("C1");`)

私はあなたの質問を理解していません、私は思います:あなたは実行時に与えられたタイプに動的にキャストしたいですか?これは静的に型付けされた言語では不可能です!あなたができることは、クラス(または何でも)をパスとして渡しvoid*、switch…caseを使用して、必要なタイプにキャストすることです(これも使用できますがstd.variant、これはおそらくより良い方法ですが、私はこれを使用したことがありません)。次に、さまざまな関数(テンプレート関数)を呼び出します。

final switch(which_type) {
    case "C1": foo(cast(C1)bar); break;
    case "C2": foo(cast(C2)bar); break;
}

void foo(T)(T a) {
}

コンパイル時にスイッチケースを生成することもできます。

final switch(which_type) {
    foreach(i; TypeTuple("C1", "C2")) {
        case i: foo(mixin(`cast(` ~ i ~ `)bar`); break;
    }
}

タイプの文字列を取得したいだけの場合は、typeof(bar).stringofタイプをbar文字列として提供します(ただし、これはコンパイル時にすでにわかっています)。

于 2012-07-19T18:14:24.067 に答える
5

ミックスインはコンパイル時のアーティファクトであり、コンパイル時にのみ使用できます。typeofコンパイル時にのみ使用できます。Dは静的に型付けされた言語であり、すべての型はコンパイル時に認識されている必要があります。

派生クラスインスタンスを参照する基本クラスタイプの参照を持つことができるので、次のようなことが可能です。

C makeC(string type)
{
    switch(type)
    {
        case "C": return new C;
        case "C1": return new C1;
        case "C2": return new C2;
        default: throw new Exception(format("%s is not a C", tye));
    }
}

C c = makeC("C1");

std.variantさまざまなタイプを保持するために使用できるものもあります(内部でユニオンを使用します)。

ただし、Dは静的に型付けされているため、実行時に変数の型を決定することはできません。

于 2012-07-19T18:24:25.700 に答える