2017-11-29 7 views
1

私はセイロンを勉強しており、メタモデルについて質問があります。私はいくつかの基本クラス '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`) {} 

識別子クラスは、データコンテナのクライアントです。私はこのソリューションが全体的に好きですが、スーパークラスコンストラクタに 'class'を渡す必要があります。なぜなら、DataContainer内で 'class'を使用すると、サブクラスのメンバーは表示されないからです。 基本クラスメソッドで拡張クラスのメンバーの実際のリストを取得するにはどうすればよいですか? 「this」のようなものが動作しません...

答えて

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

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