7

レーダーを提出する前に、コミュニティでサニティ チェックを行います。

.h Obj-C ファイル:

@protocol myProto <NSObject> 
@end

.swift ファイル (ブリッジング ヘッダー経由で上記のプロトコル定義にアクセスできるファイル):

class myClass {
    // This line compiles fine
    var dictOne: [NSObject:Int]?
    // This line fails with "Type 'myProto' does not conform to protocol 'Hashable'"
    var dictTwo: [myProto:Int]?
}

NSObject クラスを調べると、それ (またはマップ先の NSObjectProtocol) が Hashable プロトコルで必要な hashValue メソッドを実装しておらず、明示的に採用していないことがわかります。

そのため、舞台裏のどこかで NSObject はこれにもかかわらず Hashable としてフラグが立てられていますが、NSObject/NSObjectProtocol を採用するプロトコルには拡張されていません。

バグがありますか、それとも何か不足していますか?

:) テオ

追加情報:

ドキュメントでは、次のことが示唆されています。

  • ディクショナリのキー タイプの唯一の要件は、それが Hashable であり、実装されていること==です。
  • 実際にプロトコルを使用できます。
ディクショナリ キー タイプのハッシュ値

ディクショナリのキー型として使用するには、型をハッシュ可能にする必要があります。つまり、型はそれ自体のハッシュ値を計算する方法を提供する必要があります。ハッシュ値は、a == b の場合、a.hashValue == b.hashValue となるように、等しいと比較されるすべてのオブジェクトで同じ Int 値です。

Swift のすべての基本型 (String、Int、Double、および Bool など) はデフォルトでハッシュ可能であり、これらの型はすべて辞書のキーとして使用できます。値が関連付けられていない列挙メンバー値 (「列挙」で説明) も、デフォルトでハッシュ可能です。

注: Swift の標準ライブラリの Hashable プロトコルに準拠させることで、独自のカスタム型を辞書キー型として使用できます。Hashable プロトコルに準拠する型は、hashValue と呼ばれる取得可能な Int プロパティを提供する必要があり、「等しい」演算子 (==) の実装も提供する必要があります。型の hashValue プロパティによって返される値は、同じプログラムの異なる実行間、または異なるプログラムで同じである必要はありません。プロトコルへの準拠の詳細については、プロトコルを参照してください。

4

3 に答える 3

11

NSObjectProtocolから継承しませんHashable。ここが決定的な問題です。

と呼ばれるメソッドが必要であるのに対し、と呼ばれるメソッドが必要なHashableため、実際には継承できません。HashablehashValueNSObjectProtocolhash

一方、NSObjectクラスは と の両方NSObjectProtocolを実装できますHashable

で同じ問題が発生しEquatableます。

編集:

さらに微妙な問題がもう 1 つあります。が期待される場所でプロトコルを使用することはできませんEquatable。常にクラス型または を採用する値型を使用する必要がありますEquatable。その理由は、キーが を採用するだけでは不十分でありEquatable、ディクショナリ内のすべてのキーが互いに同等である必要があるためです。

たとえば、 クラスAと クラスがありB、どちらも に準拠しているEquatable場合、のインスタンスを の他のインスタンスと比較したりA、 のインスタンスを の他のインスタンスとA比較したりできますがB、 のインスタンスを のインスタンスと比較Bすることはできません。そのため、 のインスタンスと のインスタンスを同じ辞書でキーとして使用することはできません。ABAB

NSObjecteveryは他の と同等であることに注意してくださいNSObject。したがってNSObject、辞書内のキーに許可されている型です。

于 2014-07-24T16:57:05.253 に答える