web-dev-qa-db-ja.com

Swiftでゲッターをオーバーライドする

プロパティのゲッターをオーバーライドする必要がある状況があります。

私たちが持っているとしましょう:

public class MyBaseClass {
    private var _name: String
    public internal(set) var name: String {
        get {
            return self._name
        }
        set {
            self._name = newValue
        }
    }
}

本当に素晴らしいものは何もないと思います。

さて、派生クラスでゲッターをオーバーライドしようとすると:

public class MyDerivedClass: MyBaseClass {
    public var name: String {
        get {
            return "Derived - \(super.name)"
        }
    }
}

コンパイルエラーが表示されます:可変プロパティを読み取り専用プロパティ 'name'でオーバーライドできません。

セッターを追加してオーバーライドしようとすると:

public class MyDerivedClass: MyBaseClass {
    public internal(set) var name: String {
        get {
            return "Derived - \(super.name)"
        }
        set {
            super.name = newValue
        }
    }
}

エラーが発生します:オーバーライドするvarのセッターは、オーバーライドする宣言と同じようにアクセス可能でなければなりません。

そして、私が次を試してみると:

public class MyDerivedClass: MyBaseClass {
    public internal(set) var name: String {
        get {
            return "Derived - \(super.name)"
        }
    }
}

次に、コンパイラがクラッシュします...

ゲッターのみをオーバーライドするにはどうすればよいですか?

27
BPCorp

これは私のために働く:

_    public class MyBaseClass {
        private var _name: String = "Hi"
        public internal(set) var name: String {
            get {
                return self._name
            }
            set {
                self._name = newValue
            }
        }
    }

    public class MyDerivedClass:MyBaseClass {
        override public var name: String {
            get {
                return "Derived - \(super.name)"
            }
            set {
                super._name = newValue
            }
        }
    }

    MyDerivedClass().name
_

[〜#〜] edit [〜#〜]

このコードは遊び場で動作し、Sources-> SupportCode.Swiftファイルに配置します

_    public class MyBaseClass {
    private var _name: String = "Hi"
    public internal(set) var name: String {
        get {
            return self._name
        }
        set {
            self._name = newValue
        }
    }
    public init() {

    }

    }

    public class MyDerivedClass:MyBaseClass {
        override public var name: String {
            get {
                return "Derived - \(super.name)"
            }
            set {
               // do nothing
            }
        }
       public override init() {

        }
    }
_

internal(set)をオーバーライドされたサブクラス変数の前に配置できないという同じ警告が表示されるので、少し厄介です。バグかもしれません。また、派生クラスのセッターが何もしないことを確認するために不正行為をしています。

internal(set)またはprivate(set)のより一般的な使用法は、次のようなコードを使用することです。これは、ドキュメントのコードと似ています。

_public class MyBaseClass {
    public private(set) var _name: String = "Hi"
    public var name: String {
        get {
            return self._name
        }
        set {
            self._name = newValue
        }
    }
    public init() {

    }

}

public class MyDerivedClass:MyBaseClass {
    override public var name: String {
        get {
            return "Derived - \(super.name)"
        }
        set {
           super._name = newValue
        }
    }
   public override init() {

    }
}
_

ここで、セッターはMyDerivedClass()._nameで直接読み取ることができますが、変更することはできません。このMyDerivedClass()._name = "Fred"はエラーを発生させますが、MyDerivedClass().name = "Fred"は問題ありません。

25
sketchyTech

問題1

MyBaseClass コンパイルしない

  1. 格納されたプロパティ(_name)があります
  2. この保存されたプロパティはオプションではないため、nilにはできません
  3. それを設定する初期化子はありません

まず最初に、適切な初期化子をMyBaseClassに追加する必要があります

public class MyBaseClass {
    private var _name: String
    public internal(set) var name: String {
        get { return self._name }
        set { self._name = newValue }
    }
    init(name : String){
        _name = name
    }
}

問題2

これで、計算されたプロパティをオーバーライドするMyDerivedClassを宣言できます。

  1. マジックキーワードオーバーライドを使用する必要があります
  2. セッターとゲッターの両方を提供する必要があります

コードは次のとおりです。

public class MyDerivedClass: MyBaseClass {
    public override var name: String {
        get { return "Derived - \(super.name)" }
        set { super.name = newValue }
    }
}

テスト

私の遊び場から:

let somethingWithAName = MyDerivedClass(name: "default name")
println(somethingWithAName.name) // > "Derived - default name"
somethingWithAName.name = "another name"
println(somethingWithAName.name) // > "Derived - another name"
6
Luca Angeletti