2016-04-28 16 views
0

スウィフトは、オブジェクトのプロパティの1つを設定するためにオブジェクト(プロトコル)にアクセスするためにのみ使用されている場合、プロパティの設定者を呼び出さなければならない理由を教えてください。この最初の例では、私が設定可能として間接オブジェクトを宣言していない場合、私は取得エラーを示しています読み取り専用のプロパティによるスウィフトプロトコル設定可能なプロパティ

protocol AProtocol { 
    var name: String { get set } 
} 

class AnImplementation: AProtocol { 
    var name = "" 
} 

class AParent { 
    var test = AnImplementation() 
} 

class AChild { 
    var parent: AParent! 

    var test: AProtocol { 
     get { return parent.test } 
     // Note: Not settable 
    } 
} 

var parent = AParent() 
var child = AChild() 
child.parent = parent 

child.test.name = "Hello world!" // Error: Cannot assign to property : 'test' is a get-only property 
print(child.test.name) 

私はそれをセッターを与えると、それはコンパイルし、動作しますが、それはセッターを呼び出します。

protocol AProtocol { 
    var name: String { get set } 
} 

class AnImplementation: AProtocol { 
    var name = "" 
} 

class AParent { 
    var test = AnImplementation() 
} 

class AChild { 
    var parent: AParent! 

    var test: AProtocol { 
     get { return parent.test } 
     set(newTest) { print("Shouldn't be here!") } 
    } 
} 

var parent = AParent() 
var child = AChild() 
child.parent = parent 

child.test.name = "Hello world!" 
print(child.test.name) 

出力は次のとおりです。

Shouldn't be here! 
Hello world! 

私はここで理解していないよ何かわかりません。私は空のセッターを与えることができますが、その理由を理解したいと思います。

大変ありがとうございます!

答えて

2
これにあなたのプロトコルの宣言を変更

protocol AProtocol:class { 
    var name: String { get set } 
} 

そうでなければ、それは値型としてデフォルトで取られます。値タイプのプロパティを変更すると、値タイプのインスタンスが置き換えられます(setterオブザーバのように)。参照がletの参照であれば、それを行うことはできません。

+0

値型のセッターについては、たとえば私の答えを参照してください。http://stackoverflow.com/a/33901138/341994 – matt

2

これはおそらく、AChild.testがクラスであるか値型であるかをコンパイラが認識しないことが原因です。クラスでは問題はありませんが、nameに割り当てられた値型では、test(値コピー動作)への代入も作成されます。 APProtocolclassというプロトコルに設定すると、問題が解決されます。それは両方のクラスと値のタイプのために動作しますので、

var tmp = child.test 
tmp.test = "Hello world!" 
child.test = tmp 

:コンパイラはtestが値またはクラス型があるかどうかわからないときに

は、展開するには、それは child.test.name = "Hello world!"次の書き換えを使用します。