2017-11-29 4 views
1

실론을 연구 중이고 메타 모델에 대한 질문이 있습니다. 일부 빌드를 생성하여 기본 클래스 인 'DataContainer'를 작성하여 빌드 - 인 equals-hash 구현으로 불변 클래스를 인스턴스화 할 수 있습니다. 예 : 식별자 (125, "ab") == 식별자 (125, "ab") 그래서 기본 클래스는 모든 공유 변수가 아닌 값을 수집하고이 정보를 'hash'및 'equals'메소드에서 사용해야합니다. 이 코드를 썼다 :실론 메타 모델

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

식별자 클래스는 DataContainer의 클라이언트입니다. 전체적으로이 솔루션이 마음에 들지만 슈퍼 클래스 생성자에 '클래스'를 전달해야합니다. 왜냐하면 DataContainer 내부에서 '클래스'를 사용하면 하위 클래스의 멤버가 표시되지 않기 때문입니다. 기본 클래스 메서드에서 확장 클래스 멤버의 실제 목록을 얻으려면 어떻게합니까? 'this'와 같은 것이 작동하지 않습니다 ...

답변

1

저는 실론 커뮤니티의 사람들 덕분에 솔루션을 발견했습니다. '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() {} 
:

이 최종 코드

관련 문제