5

クラス A は文字列値を提供します。クラス B は、内部に A 型の 2 つのメンバーを持ち、計算されたプロパティ "v" を提供して、それらのいずれかを選択します。

class A {
    var value: String

    init(value: String) {
        self.value = value
    }
}

class B {
    var v1: A?
    var v2: A = A(value: "2")

    private var v: A {
        return v1 ?? v2
    }

    var value: String {
        get {
            return v.value
        }
        set {
            v.value = newValue
        }
    }
}

このコードはシンプルで機能します。A と B の両方にメンバー「値」があるため、次のようなプロトコルにします。

protocol ValueProvider {
    var value: String {get set}
}

class A: ValueProvider {
    var value: String

    init(value: String) {
        self.value = value
    }
}

class B: ValueProvider {
    var v1: ValueProvider?
    var v2: ValueProvider = A(value: "2")

    private var v: ValueProvider {
        return v1 ?? v2
    }

    var value: String {
        get {
            return v.value
        }
        set {
            v.value = newValue // Error: Cannot assign to the result of the expression
        }
    }
}

次のコードを変更すると

v.value = newValue

var v = self.v
v.value = newValue

それは再び動作します!

これは Swift のバグですか、それともプロトコルの特性に特有のものですか?

4

1 に答える 1

11

プロトコルをプロトコルとして定義する必要がありclassます。

protocol ValueProvider : class {
    var value: String {get set}
}

それで

var value: String {
    get { return v.value }
    set { v.value = newValue }
}

v1期待どおりにコンパイルして動作します (つまり、 ifによって参照さv1 != nilれるオブジェクトと、それ以外によって参照されるオブジェクトに新しい値を割り当てv2ます)。

vタイプ の読み取り専用計算プロパティですValueProvider。プロトコルをクラス プロトコルとして定義することにより、コンパイラはそれv参照型v.valueであることを認識するため 、参照自体が定数であってもそのプロパティを変更できます。

vプロパティにA参照型の型があるため、最初のコード例が機能し ます。

そしてあなたの回避策

set {
    var tmp = v1 ?? v2
    tmp.value = newValue
}

変数の (読み書き) プロパティはどのような場合 (値型または参照型) にも設定できるため、機能します。

于 2015-04-19T11:10:49.347 に答える