2017-09-14 8 views
0

== 연산자와 hashCode 메서드를 재정의해야하는 새로운 클래스에서 이상한 동작이 발생합니다.Dart : 클래스 생성 된 hashCode와의 이상한 동작

예를 들어 드리겠습니다. 이제

import 'package:quiver/core.dart'; 
import 'package:collection/collection.dart'; 

class Test { 

    List testList = []; 

    operator ==(Object other) { 
    if (other is! Test) return false; 
    Function deepEq = const DeepCollectionEquality.unordered().equals; 
    return deepEq(testList, (other as Test).testList); 
    } 

    int get hashCode => hashObjects(testList); 
} 

내가 다음 코드를 실행합니다 : 내가 기대했던

main() { 
    Test test = new Test(); 
    //test.testList.add([]); 
    print('Test, hash: ${test.hashCode}'); 
    Test test_2 = new Test(); 
    //test_2.testList.add([]); 
    print('Test_2, hash: ${test_2.hashCode}'); 
    print("is ${test == test_2} that Test and Test2 are equal"); 
    Function deepEq = const DeepCollectionEquality.unordered().equals; 
    bool b = deepEq(test, test_2); 
    print("is $b that Test and Test2 are deep equal"); 

    List l1 = [test]; 
    print('L1 hash: ${l1.hashCode}'); 
    List l2 = [test_2]; 
    print('L2 hash: ${l2.hashCode}'); 
    deepEq = const DeepCollectionEquality.unordered().equals; 
    b = deepEq(l1, l2); 
    print("is $b that List1 and List2 are deep equal"); 
} 

위의 코드 인쇄 다음을, 즉 무엇 의 우리는 다음과 같이 구성되어 테스트 클래스가 그쪽으로 가정 해 봅시다 :

test.testList.add([]); 
    test_2.testList.add([]); 
:

Test, hash: 0 
Test_2, hash: 0 
is true that Test and Test2 are equal 
is true that Test and Test2 are deep equal 
L1 hash: 89819481 
L2 hash: 414841104 
is true that List1 and List2 are deep equal 

는 지금은 라인의 주석을 해제하는 경우

Test, hash: 76603616 
Test_2, hash: 386421917 
is true that Test and Test2 are equal 
is true that Test and Test2 are deep equal 
L1 hash: 915458568 
L2 hash: 503799923 
is false that List1 and List2 are deep equal 

이 내가 기대했던되지 않습니다 : 17,451,515,

와 나는 다음과 같은 결과를 가지고, 프로그램을 다시 실행하십시오. DeepCollectionEquality가 내부적으로 hashCode를 사용하여 동등성을 검사했다는 것을 감안할 때 hashList는 주 목록의 List as 구성 요소를 발견하면 모든 구성 요소를 읽는 새 List를 생성하는 대신 List hashCode를 사용한다는 것을 이해할 수 있습니다. List1과 List2가 아닌 동안 Test와 Test 2가 똑같은 것으로 간주되는 이유는 무엇인지 이해할 수 없습니다. 해시 코드를 생성하는 Iterable에 얼마나 많은 내부 목록이 있는지에 따라 다릅니다. HashObjects는 의도적으로 작동하거나 버그로 간주되어야합니까? hashObjects 사용 방법에 문제가 있습니까?

답변

0

문제는 hashObjects()이 반복되지 않으며 빈 목록의 두 인스턴스가 서로 다른 해시 값을 갖습니다 (둘 다 const 또는 우연한 경우가 아니면).

따라서 hashObjects()은 각 하위 목록이 동일한 개체 (구조적으로 동일하지 않은 경우)가 아니라면 플랫 목록에 대해서는 기대 한대로 작동하지만 목록의 목록에는 적합하지 않습니다. 라이머

import 'package:quiver/core.dart'; 

void main() { 
    var a = []; 
    var b = []; 
    var c = []; 
    print(a.hashCode); // different 
    print(b.hashCode); 
    print(hashObjects(a)); // both same, both zero 
    print(hashObjects(b)); 
    print(hashObjects(a..add(1))); // both same 
    print(hashObjects(b..add(1))); 
    print(hashObjects(a..add(c))); // both same, because `c` is identical 
    print(hashObjects(b..add(c))); 
    print(hashObjects(a..add([]))); // different, because the two empty 
    print(hashObjects(b..add([]))); // lists are not identical. 
} 
+0

감사합니다, 나는이 버그 고려해야한다, 또는 의도적으로 그런 식으로 작동 : 다음 예는해야

이 보여? –

+0

명확하게 문서화되어 있지는 않지만, 데이터를 트래버스하는 올바른 방법이 임의의 데이터 구조 (예 : 건너 뛰기를 원할지도 모르는 캐시 항목을 생각할 때)에 어떤 것이 될지 항상 명확하지 않기 때문에 이것이 의도적이라고 생각합니다. 해시 코드 라이브러리는 상당히 기본적인 빌딩 블록으로 구성되어 있습니다. –

+0

떨림 문서 (예 : [here] (https://www.dartdocs.org/documentation/quiver/0.25.0/quiver.core/hashObjects.html))에 명시된 외침이 도움이 될까요? "hashObjects가 반복적으로 iterable을 걷지 않는다는 점에 유의하십시오." – filiph