2017-09-14 18 views
0

==演算子とhashCodeメソッドをオーバーライドしなければならなかった新しいクラスで奇妙な動作をしています。Dart:クラス生成されたhashCodeでの不思議な動作

例を挙げます。 のは、我々は次のように行われるテストクラスを持っているTHAを言ってみましょう:

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 

これは私が期待したものではありません:

とは、私は次の結果を持って、プログラムを再実行します。 DeepCollectionEqualityが内部的にhashCodeを使って等しいかどうかを確認すると、hashListはメインListのList asコンポーネントに遭遇したときに、hashCodeを使用して、すべてのコンポーネントを読み込む新しいhashCodeを生成するのではなく、私が理解していないのは、List1とList2がそうではないうちに、TestとTest 2が同じだと考えられる理由です。 ハッシュコードを作成しているIterableに内部リストのレベルがいくつあるかによって異なります。 HashObjectsは設計通りに動作しますが、これはバグと見なされるべきですか? hashObjectsの使い方に何か問題がありますか?

答えて

0

問題はhashObjects()が再帰しないことと、空リストの2つの異なるインスタンスが異なるハッシュ値を持つことです(ただし、両方が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

震えのドキュメント([ここ](https://www.dartdocs.org/documentation/quiver/0.25.0/quiver.core/hashObjects.html))の明示的なコメントは役に立ちますか?何かのように: "hashObjectsは反復的にiterableを歩かないことに注意してください。 – filiph

関連する問題