さまざまなことを表現しています。
func check(object: inout Healthy) {
でobject
引数はどのHealthy
準拠したインスタンスをすることができます。したがって、あなたがこれを行うことができます:
protocol Healthy {}
struct Foo : Healthy {}
struct Bar : Healthy {}
func check(object: inout Healthy) {
object = Bar()
}
var h: Healthy = Foo()
check(object: &h)
print(h) // Bar()
を我々はcheck(object:)
と呼ばれ、h
を通過した(Foo
インスタンスを保持する)inout
引数として、しかしBar
インスタンスを保持h
になってしまいました。
具体的にはcheck(object:)
を具体的な型のinout
引数で呼び出すことはできません。以下はコンパイルされない:Foo
変数に割り当てないobject
引数に任意Healthy
適合するインスタンスを割り当てることができ
var h = Foo()
// compiler error: Cannot pass immutable value as inout argument:
// implicit conversion from 'Foo' to 'Healthy' requires a temporary
check(object: &h)
check(object:)
ので。
func check<T : Healthy>(object: inout T) {
object
引数としかしながら
は、Healthy
に準拠単一特定具象型である(このタイプは、コールサイトで満たされています)。 inout
引数として渡される変数型と互換性がない可能性があるため、任意のHealthy
に準拠するインスタンスを割り当てることはできません。
これで、具体的なタイプのinout
引数で呼び出すことができるようになりました。私たちは今、言うことができます:
protocol Healthy {
var alive: Bool { get set }
}
struct Foo : Healthy {
var alive: Bool
}
struct Bar : Healthy {
var alive: Bool
}
func check<T : Healthy>(object: inout T) {
object.alive = false
// illegal
// object = Bar()
}
var h = Foo(alive: true)
check(object: &h)
(ノートh
がFoo
として入力することが可能である)
だから、ほとんどの場合、あなたはおそらく、むしろプロトコルに型指定されたinout
を持つよりも、この方法は一般的なようにしたいでしょうパラメータは、具体的な型を扱う可能性が高いためです。
あなたの答えから、私は、この例でジェネリックを使用する主な理由は、関数内での代入を避けることであると推測しています(この場合、inoutパラメータを指定すると概念的に間違っています)。正しい? – aneuryzm
@パトリックジェネリックを使う主な理由は、 'inout'引数が単一の具体的な型であることを強制することです(具体的な型の変数を' inout Healthy'パラメータに渡すことはできません)。関数内の代入を避けることはできますが、引き続き引数に代入することはできますが、コンパイラは指定する型が 'T'型であり、*任意の*' Healthy'適合型ではないことを強制します。 – Hamish
@Patrickたとえば、 'func check(オブジェクト:inout T、other:T){object = other}'は合法です。 'inout'引数に割り当てる能力は概念的に間違っているわけではありません - それは' inout'を使うことが可能な機能です。 –
Hamish