protocol ProtocolA {}
protocol ProtocolB: ProtocolA {}
enum MyEnum<T: ProtocolA, U: ProtocolB> {
case A(T)
case B(U)
}
struct AThing: ProtocolA {}
struct BThing: ProtocolB {}
let bThing = BThing()
let thing = MyEnum.B(bThing) // error: cannot invoke 'B' with an argument list of type '(BThing)'
ここでは、DataObject
を必要とせずに同じ問題が発生しています。なぜこれは失敗するのですか?
MyEnum
は一般的です。つまり、具体的な型を作成するには、型の種類がT
とU
であることが必要です。これらのタイプに制約を与えました(1つはProtocolA
に、もう1つはProtocolB
に準拠しています)。
我々は、この行を取得:
let thing = MyEnum.B(bThing)
thing
は何タイプ?型推論では、U
が何であるか分かりますが、T
とは何ですか?
let thing: MyEnum<?, BThing> = MyEnum.B(bThing)
はそれを動作するように、ここで十分な文脈だけではありませんので、我々は明示的にコンパイラに指示する必要があります。
let thing = MyEnum<AThing, BThing>.B(bThing)
をそうthing
の完全なタイプはMyEnum<OtherAThing, BThing>
とは異なるタイプである、MyEnum<AThing, BThing>
です。 (正確に[Int]
ようlet xs = []
は、明示的な型定義せずにコンパイルされません理由である、[String]
とは異なるタイプである。)作品
あなたの第二の例は、汎用ではないので、何も問題はありません。バウンドtypealiasesだけの種類の名前を変更
enum MyEnum {
case A(ProtocolA)
case B(ProtocolB)
}
、彼らは新しいタイプを作成していない(非結合typealiasたい、またはなどスウィフト2.2呼び出して、associatedtype
):それはに簡素化します。したがって、A
にはProtocolA
が、B
にはいずれもProtocolB
、すべてのMyEnum
には同じタイプが割り当てられます。
コンパイラが混乱しているため、このエラーは残念です。これを最も基本的なケースに単純化すると、より明確なエラーが発生します。これはあなたの例とまったく同じ理由で失敗します。
enum MyEnum<T> {
case A
}
let x = MyEnum.A // error: generic parameter 'T' could not be inferred
説明をありがとう!これは私がここでもっと頻繁に見たいと思っているゴールドの答えです;実際にはエラーは非常に不幸です:) 今は 'typealias'の解決策に固執します。関連するプロトコルに準拠したものを私に渡すことができます。 (ジェネリックのソリューションのように)。私は、このようなことをするのではなく、入力を1つのプロトコルに限定することを制限していると思います。 '' T:ProtocolA、T:ProtocolC> '? – Cabus
私はあなたがその制約から何を期待しているのか分かりません。あなたは「または」を意味しますか?それが事実なら、Tのタイプは何ですか?どのような方法で呼び出すことができますか? 1つのタイプを持つ必要があります。オーバーラップするプロトコルのグループがいくつかある場合、それらがすべて準拠している別のプロトコルを作成できます。 –
遅れて申し訳ありません。私は以来、別のソリューションに移行しました。とにかく助けてくれてありがとう。ただし、 こちらをご覧くださいhttp://www.youtube.com/watch?v=gaXSbqo3iKA&t=2m54s それはうまくいくはずですか? – Cabus