Swift : 変数の後に{ }・・これはComuputedプロパティ(get/set)というものです。

〽️ get/setを理解しよう。







stored/computedプロパティ。

こんにちは、「ふ」です。
Swiftにおける普通の変数。

var fu:Int = 1

当たり前に書いてますよね。
しかし技術書のコードなどを見ていると、こういうのが出てきます。

var he { 「「3//処理内容」」 }

変数のあとに{ }で囲まれた処理が書いてある。これはなんぞや?



〜普段使っている変数や定数は「値」を直接格納する、stored(格納型)プロパティと呼ばれています。それに対して上に書いた変数は、computed(計算された)プロパティと呼ばれるものです。


computedプロパティは、自身は決まった値を持っておらず、他のプロパティの値を元に処理を行い結果を返す挙動をします。
今回はこのcomputedプロパティについて調べていきましょう。





まずgetから。

computedプロパティには、 読み取り専用のgetメソッドと書き込み用のsetメソッドがあります。まずはgetメソッドのみのプロパティを作ってみましょう。

正方形についてのクラス「Square」を作ります。その中に一辺の長さを表す変数「side」を宣言しました。

class Square { 「「3//1辺の長さ」」 var side:Int = 2 }

computedプロパティ(getのみ)は次のように記述します。

「「4var」」 変数名 : 型 { 「「4get」」 { 処理内容 「「4return」」 返り値 } }

クラス「Square」に面積を表す変数「area」を加えましょう。一辺の長さ「side」を元に値を返すよう、getメソッドを設定します。

class Square { 「「3//1辺の長さ」」 var side:Int = 2 「「3//面積」」 var area:Int { 「「1get { return side*side }」」 } }

Squareクラスのインスタンス「s1」を作り、プロパティの値を調べてみます。

var s1 = Square() print(s1.side) 「「1▶︎ 2」」 print(s1.area) 「「1▶︎ 4」」

「area」を出力するとgetメソッド「area*area」が実行されて返ってきます。

扨(さて)、getメソッドのみ定義したcomputedプロパティは「読み取り専用」となります。試しにインスタンスの外部から値を書き換えてみると・・

s1.area = 3 「「4▶︎ エラー "Cannot assign to property: 'area' is a get-only property"」」

ちゃんとエラーとなってくれます。外部から変更されたくないプロパティを設定するときに使えそうですね。






setメソッド。

次にsetメソッドを書き加えてみましょう。setメソッドは、クラスの中で(直下で)宣言されている変数(メンバ変数)に値をセットするメソッドです。
〜と言うとややこしく感じるかもですが、クラス「Square」のメンバ変数はこれですね。

class Square { var side:Int = 2 「「1⬆︎メンバ変数」」 }

このメンバ変数に値をセットするメソッド、setを書いていきます。記述の仕方は以下のようになります。

「「4var」」 変数名 : 型 { 「「4get」」 { 処理内容 「「4return」」 返り値 } 「「4set」」(引数) { 処理内容 } }

先ほどgetメソッドのみのcomputedプロパティを作りましたが、setメソッドは単独では使えません。必ずgetメソッドも定義するようにしましょう。
変数「area」にsetを追加してみます。

class Square { var side:Int = 2 var area:Int { get { return side*side } 「「1set(num) { side = num*side }」」 }

変数「area」の値を「引数*area」とする処理を記述しました。
getの時と同様、Squareのインスタンスを作り、内容を調べてみます。

「「3//インスタンスを生成」」 var s2 = Square() 「「3//areaに値をセットする。setを記述しているので今度はエラーにならない」」 s2.area = 2 「「3//areaを出力してみる」」 print(s2.area) 「「1▶︎ 16」」

何が起きているんだ?

???の方も多いと思います。s2.areaに「2」を代入したのに、s2.areaの値を呼び出すと「16」となるのです。内部で何が起きているのでしょうか。
1つ1つ見ていきましょう。







こうなっている。

var s2 = Square()

インスタンスを生成する、これは普通ですよね。

s2.area = 2

これは何をやっているのでしょうか。
そう、ここがsetメソッドを理解する上での1番の難解ポイントです。


これは、

setの引数に値を代入する。

という操作を行っているのです。

     「「1⬇︎」」 set(「「1num」」) { side = 「「1num」」*side }

ちょっと特殊な記述方法にも思えますが、「s2.area」に外部から値を代入すると、setの引数にその値が指定されます。
するとそこでsetメソッドが実行され、メンバ変数「side」の値が置き換えられます。置き換えられた「side」の値を見てみましょう。

s2.area = 2 「「3//引数を「2」としたsetが実行され、sideが書き換えられる。」」 print(s2.side) 「「1▶︎ 4」」

このあと「s2.area」を呼び出すと、書き換えられた「side」の値を元にsetメソッドが実行されてその値が返ってきます。

print(s2.area) 「「3//書き換えられたsideの値「4」を元にgetが実行される。」」 「「1▶︎ 16」」

computedプロパティのsetとget、どちらを発動させるかは書き込み操作、読み取り操作をそれぞれ行う事で振り分けられます。

書き込み操作

s2.area = 2

s2に値を指定するとsetが発動してメンバ変数の値を操作する。

読み取り操作

print(s2.area)

s2を呼び出すとgetが発動し、変更されたメンバ変数を元に処理を行い値を返す。



省略形。

computedプロパティのsetとgetの仕組み、お分かりいただけたでしょうか?

扨(さて)、computedプロパティは省略型で記述されていることもしばしばあります。最後によくある2つのパターンを紹介しておきますね。

◼︎その1。読み取り専用のプロパティの場合、「 get { } 」の括りを省略することができます。

class Square2 { var side:Int = 2 「「1var area:Int { return side*side }」」 }

この「area」の表記は、

var area:Int { get { return side*side } }

と同じことになります。

◼︎その2。setメソッドの引数を記述しなかった場合、引数名は「newValue」となります。

class Square2 { var side:Int = 2 var area:Int { get { return side*side } 「「1set { side = newValue*2 }」」 } }

ただしsetを記述したときは読み取り専用ではなくなるので、「 get { } 」の括りは省略せずに記述しましょう。

インスタンスを作って動きを確認してみます。

「「3//インスタンスを生成」」 var s3 = Square2() 「「3//そのままの状態でgetを呼び出す」」 print(s3.area) 「「1▶︎ 4」」 「「3//書き込み操作を行うと引数「newValue」に値がセットされ、setメソッドが発動」」 s3.area = 2 「「3//メンバ変数が書き換えられたことを確認」」 print(s3.side) 「「1▶︎ 4」」 「「3//再びgetを呼び出す」」 print(s3.area) 「「1▶︎ 16」」

setメソッドの引数名は「newValue」として扱われている事が確認できます。
これら2つの省略型はよく登場するので、覚えておいたほうがよろしいかと。


如何でしたか?今回はcomputedプロパティについて紹介しました。長い記事になってしまいましたがお付き合いくださった方、ありがとうございます!
これでもう、変数の後ろに「 { } 」が付いたコードが出てきてもビビらなくてすみますね ♫

◼︎関連記事













「ふ」です。

swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。

🐧 twitter 🐧