【问题标题】:Ceylon metamodel锡兰元模型
【发布时间】:2017-11-29 20:49:40
【问题描述】:

我正在研究 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 的客户端。我整体上喜欢这个解决方案,但我必须将“类”传递给超类构造函数,因为如果我在 DataContainer 中使用“类”,它就看不到任何子类的成员。 如何在基类方法中获取扩展类成员的实际列表? 像'this'这样的东西不起作用......

【问题讨论】:

    标签: reflection metamodel ceylon


    【解决方案1】:

    感谢锡兰社区的人们,我找到了解决方案。应使用 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() {}
    

    【讨论】:

    • 应该是DataContainer还是extends Object()
    【解决方案2】:

    除了 Alexander 令人生畏的答案之外,我还冒昧地实现了一个 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多