私は同様の問題を抱えていて、役立つかもしれないものを思いついたので、解決策を探したときに最初に見つけた場所の1つであるため、将来の参考のために共有したいと思います.
上で述べたように、問題は copy() 関数の戻り値の型があいまいであることです。これは、copy() -> C と copy() -> P 関数を分離することで非常に明確に説明できます。
したがって、プロトコルとクラスを次のように定義するとします。
protocol P
{
func copy() -> P
}
class C:P
{
func doCopy() -> C { return C() }
func copy() -> C { return doCopy() }
func copy() -> P { return doCopy() }
}
戻り値の型が明示的である場合、これはコンパイルされ、期待される結果を生成します。コンパイラが戻り値の型を (独自に) 決定する必要がある場合はいつでも、状況があいまいであることに気づき、P プロトコルを実装するすべての具象クラスで失敗します。
例えば:
var aC:C = C() // aC is of type C
var aP:P = aC // aP is of type P (contains an instance of C)
var bC:C // this to test assignment to a C type variable
var bP:P // " " " P " "
bC = aC.copy() // OK copy()->C is used
bP = aC.copy() // Ambiguous.
// compiler could use either functions
bP = (aC as P).copy() // but this resolves the ambiguity.
bC = aP.copy() // Fails, obvious type incompatibility
bP = aP.copy() // OK copy()->P is used
結論として、これは、基本クラスの copy() 関数を使用していないか、明示的な型コンテキストを常に持っている状況で機能します。
具象クラスと同じ関数名を使用すると、どこでも扱いにくいコードになることがわかったので、プロトコルの copy() 関数に別の名前を使用することになりました。
最終結果は次のようになります。
protocol P
{
func copyAsP() -> P
}
class C:P
{
func copy() -> C
{
// there usually is a lot more code around here...
return C()
}
func copyAsP() -> P { return copy() }
}
もちろん、私のコンテキストと機能は完全に異なりますが、質問の精神で、私は可能な限り与えられた例に近づこうとしました.