2

私はセイロンを勉強していますが、そのメタモデルについて質問があります。組み込みの equals-hash 実装で不変クラスをインスタンス化できるようにするいくつかの基本クラス 'DataContainer' を作成したい: 例: Identifier(125, "ab") == Identifier(125, "ab")すべての共有非変数値を収集し、この情報を「ハッシュ」および「等しい」メソッドで使用します。私はこのコードを書きました:

shared abstract class DataContainer(ClassDeclaration declaration) {
    value members = {
        for (i in declaration.memberDeclarations<ValueDeclaration>())
            if (!i.variable, i.name != "hash", i.name != "string") i
    };
    variable Integer? hashCode = null;

    shared actual Boolean equals(Object that) {
        if (is DataContainer that) {
            for (item in members) {
                value thisMember = item.memberGet(this);
                value thatMember = item.memberGet(that);
                if (exists thisMember, exists thatMember) {
                    if (thisMember != thatMember) { return false; }
                } else if (thisMember exists != thatMember exists) { return false; }
            }
            return true;
        }
        return false;
    }

    shared actual Integer hash => hashCode else (hashCode = calculateHash());

    Integer calculateHash() {
        variable value result = 0;
        for(i in members) {
            if (exists member = i.memberGet(this)) {
                result = result.xor(member.hash);
            }
        }
        return result;
    }
}

class Identifier(shared Integer? id, shared String? name) extends DataContainer(`class`) {}

Identifier クラスは DataContainer のクライアントです。全体としてこのソリューションが気に入っていますが、DataContainer 内で「クラス」を使用するとサブクラスのメンバーが表示されないため、「クラス」をスーパー クラス コンストラクターに渡す必要があります。基本クラスのメソッドで拡張クラスのメンバーの実際のリストを取得するにはどうすればよいですか? 「これ」のようなものは機能しません...

4

2 に答える 2

2

Ceylonコミュニティの人たちのおかげで解決策を見つけました。「class」の代わりに、ceylon.language.meta の関数 classDeclaration(this) を使用する必要があります。

これは最終的なコードです:

shared abstract class DataContainer() {
    variable Integer? _hash = null;
    variable ValueDeclaration[]? _members = null;

    shared actual Boolean equals(Object that) {
        if (is DataContainer that) {
            for (i in members) {
                value thisMember = i.memberGet(this);
                value thatMember = i.memberGet(that);
                if (exists thisMember, exists thatMember) {
                    if (thisMember != thatMember) { return false; }
                } else if (thisMember exists != thatMember exists) { return false; }
            }
            return true;
        }
        return false;
    }

    shared actual Integer hash => _hash else (_hash = calculateHash());

    ValueDeclaration[] members => _members else (_members = [
        for (i in classDeclaration(this).memberDeclarations<ValueDeclaration>())
            if (!i.variable, i.name != "string", i.name != "hash") i
    ]);

    Integer calculateHash() {
        variable Integer result = 0;
        for (i in members) {
            if (exists member = i.memberGet(this)) {
                result = result.xor(member.hash);
            }
        }
        return result;
    }
}

class Identifier(shared Integer? number, shared String? name) extends DataContainer() {}
于 2017-12-01T16:18:01.397 に答える