锡兰元模型

时间:2017-11-29 20:49:41

标签: reflection metamodel ceylon

我正在研究锡兰,对它的元模型有疑问。我想创建一些创建一些基类' DataContainer'允许使用内置的equals-hash实现来实例化不可变类: 例如标识符(125," ab")==标识符(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的客户端。我完全喜欢这个解决方案,但我必须通过“课程”#39;进入超类构造函数,因为如果我使用&#39; class&#39;在DataContainer中,它没有看到子类的任何成员。 如何在基类方法中获取扩展类成员的实际列表? 类似于这个&#39;没有工作......

2 个答案:

答案 0 :(得分:2)

我找到了解决方案,感谢来自Ceylon社区的人们。来自ceylon.language.meta的函数classDeclaration(this)应该用来代替'class'。

这是最终代码:

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() {}

答案 1 :(得分:0)

除了亚历山大的强大答案之外,我还自由地实现了string函数,因此您只需print(myObj)即可呈现漂亮的效果:

shared default actual String string {
    value s = StringBuilder();
    s.append(type(this).declaration.name).append(" { ");
    for (i in members) {
        value m = i.memberGet(this);
        s.append(i.name).append(":");
        s.append(if(exists m) then m.string else "<null>");
    }
    return s.append(" }").string;
}