web-dev-qa-db-ja.com

プロパティゲッターとセッター

この単純なクラスで私はコンパイラを手に入れています warning

自身のセッター/ゲッター内でxを変更/アクセスしようとしています

そして私がこのように使うとき:

var p: point = Point()
p.x = 12

EXC_BAD_ACCESSを受け取ります。明示的な後押しをせずにどうすればこれを行うことができますか?

class Point {

    var x: Int {
        set {
            x = newValue * 2 //Error
        }
        get {
            return x / 2 //Error
        }
    }
    // ...
}
172
Atomix

セッターとゲッターはcomputed propertiesに適用されます。そのようなプロパティはインスタンス内にストレージを持っていません - ゲッターからの値は他のインスタンスプロパティから計算されることを意味します。あなたの場合、代入するxはありません。

明示的に: "明示的なivarsの裏付けなしにこれを行うにはどうすればよいですか"。計算プロパティをバックアップするために something は必要ありません。これを試して:

class Point {
  private var _x: Int = 0             // _x -> backingX
  var x: Int {
    set { _x = 2 * newValue }
    get { return _x / 2 }
  }
}

具体的には、Swift REPLでは、

 15> var pt = Point()
pt: Point = {
  _x = 0
}
 16> pt.x = 10
 17> pt
$R3: Point = {
  _x = 20
}
 18> pt.x
$R4: Int = 10
213
GoZoner

Swiftのセッター/ゲッターは、ObjCとはまったく異なります。プロパティは、計算済みプロパティになります。つまり、ObjCの場合のように、_xなどのバッキング変数はありませんnot

以下のソリューションコードでは、xTimesTwoが何かを保存するnotが、単に computes xの結果を保存することがわかります。

計算されたプロパティの公式ドキュメント を参照してください。

また、必要な機能は Property Observers かもしれません。

必要なのは:

var x:Int

var xTimesTwo:Int {
    set {
       x = newValue / 2
    }
    get {
        return x * 2
    }
}

セッター/ゲッター内の他のプロパティを変更できます。

102
Jack

プロパティオブザーバを使用して設定値をカスタマイズできます。これを行うには、 'set'ではなく 'didSet'を使用してください。

class Point {

var x:Int {
    didSet {
        x = x * 2
    }
}
...

ゲッターは・・・.

class Point {

var doubleX: Int {
    get {
        return x / 2
    }
}
...
91
cSquirrel

GoZonerの答えを詳しく述べると:

ここでのあなたの本当の問題はあなたが再帰的にあなたのゲッターを呼んでいるということです。

var x:Int
    {
        set
        {
            x = newValue * 2 // This isn't a problem
        }
        get {
            return x / 2 // Here is your real issue, you are recursively calling 
                         // your x property's getter
        }
    }

上記のコードコメントが示すように、あなたは無限にxプロパティのgetterを呼び出しています。そしてそれはあなたがEXC_BAD_ACCESSコードを得るまで実行し続けるでしょう(あなたのXcodeの遊び場環境の右下隅にスピナーを見ることができます)。

Swiftのドキュメント :の例を考えてみましょう。

struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct AlternativeRect {
    var Origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = Origin.x + (size.width / 2)
            let centerY = Origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            Origin.x = newValue.x - (size.width / 2)
            Origin.y = newValue.y - (size.height / 2)
        }
    }
}

中央の計算プロパティが、変数の宣言内で自分自身を変更したり返したりしないことに注意してください。

29
Abdullah Bakhsh

Swift変数のsettergetterをオーバーライドするには、以下のコードを使用してください。

var temX : Int? 
var x: Int?{

    set(newX){
       temX = newX
    }

    get{
        return temX
    }
}

Getter/setterがオーバーライドされているのと同じ変数にアクセスしようとすると、無限ループが発生するため、variableの値を一時変数に保持する必要があります。

このようにセッターを呼び出すことができます

x = 10

Getterは与えられたコード行の下で起動すると呼び出されます

var newVar = x
15
Sebin Roy

xname__でxname__を定義している再帰的です。誰かがあなたに何歳かと尋ねるように?そして、あなたは「私は私の年齢の2倍です」と答えます。これは無意味です。

私はジョンの年齢の2倍または他の変数but自分であると言わなければなりません。

計算された変数は常に別の変数に依存しています。


経験則は、neverゲッター、つまりgetname__内からwithinからプロパティ自体にアクセスします。それは別のをトリガーする別のgetname__をトリガーするためです。 。 。それも印刷しないでください。印刷では、印刷する前に値を「取得」する必要があるためです!

struct Person{
    var name: String{
        get{
            print(name) // DON'T do this!!!!
            return "as"
        }
        set{
        }
    }
}

let p1 = Person()

次の警告が表示されます。

独自のゲッター内から「名前」にアクセスしようとしています。

エラーは次のようにあいまいに見えます。

enter image description here

別の方法として、didSetname__を使用することもできます。 didSetname__を使用すると、以前に設定されたばかりの値が保持されます。詳細については、 this answer を参照してください。

8
Honey

アップデート:Swift 4

以下のクラスでは、セッターとゲッターは変数sideLengthに適用されます。

class Triangle: {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) { //initializer method
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
        get { // getter
            return 3.0 * sideLength
        }
        set { //setter
            sideLength = newValue / 4.0
        }
   }

オブジェクトを作成する

var triangle = Triangle(sideLength: 3.9, name: "a triangle")

ゲッター

print(triangle.perimeter) // invoking getter

セッター

triangle.perimeter = 9.9 // invoking setter
7
Saranjith

これを使ってみてください。

var x:Int!

var xTimesTwo:Int {
    get {
        return x * 2
    }
    set {
        x = newValue / 2
    }
}

これは基本的にはJack Wuの答えですが、違いはJack Wuの答えでは彼のx変数はvar x: Intであり、私のx変数はvar x: Int!のようなものです。

6
Epic Defeater

Swift 5.1の更新

Swift 5.1の時点で、getキーワードを使用せずに変数を取得できるようになりました。例えば:

var helloWorld: String {
"Hello World"
}
0
Atalay Aşa

Swiftのセッターとゲッターは、計算されたプロパティ/変数に適用されます。これらのプロパティ/変数は実際にはメモリに格納されているのではなく、格納されているプロパティ/変数の値に基づいて計算されています。

この件に関してはAppleのSwiftのドキュメントを見てください: Swift Variable Declarations

0
jefe2000

これが理論的な答えです。それが見つかります ここ

{get set}プロパティを定数の保存プロパティにすることはできません。それは計算されたプロパティであるべきで、getとsetの両方が実装されるべきです。

0