SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

アップルの新プログラミング言語「Swift」を探検しよう

Swiftの「クラス」と「ストラクチャ」 その① ~ プロパティ、メソッド、継承、ライフサイクル

アップルの新プログラミング言語「Swift」を探検しよう 第4回


lazy属性

 変数の保持プロパティにlazyを宣言の直前につけると、インスタンス生成時ではなく、アクセス直前まで保持プロパティの右辺の式の評価を遅延させることができます。次の例をご覧ください

class SomeHeavyTask {
    init() {
        println("task generated")
    }
}
class SomeTaskManager {
    lazy var heavyTask = SomeHeavyTask()
}
var manager = SomeTaskManager()
manager.heavyTask // task generated

 lazyを付けず、従来通りの宣言方法であれば、SomeTaskManagerインスタンスの生成時にSomeHeavyTaskインスタンスが生成され、値がheavyTaskプロパティにセットされます。しかし、lazyを付けた場合には、SomeHeavyTaskインスタンスの生成は、heavyTaskプロパティへの最初のアクセス時に行われます。

 この例から見て取れるように、生成にコストのかかるクラスをプロパティに含み、インスタンス生成時には必要でない場合は、lazy属性を用いれば計算コストを削減できるでしょう。

計算プロパティ(Computed Property)

 Objective-Cではプロパティに対する取得、代入の挙動をgetter/setterでカスタマイズできました。Swiftでも同様の機能が計算プロパティ(Computed Property)として定義されています。計算プロパティはクラス、ストラクチャ、列挙型のすべてに定義可能です。先ほどのCustomRangeStructクラスと類似したモデルを見てみましょう。

struct CustomRange {
    var start: Int = 0
    var length: UInt = 0
    var end: Int {
    get {
        return start + Int(length)
    }
    set(newEnd) {
        let newLength = newEnd - start
        if newLength >= 0 {
            length = UInt(newLength)
        }
    }
    }
}
var range = CustomRange()
let end = range.end // 0
range.end = 2
let length = range.length // 2

 こちらの例のように、プロパティ宣言の直後に、

{
get {
    文
    return 計算結果
}
set(新たな値) {
    代入時の計算
}
}

という構文を入れることで、Objective-Cのgetter/setterに似たプロパティを宣言できます。動作もgetter/setterと同様で、外部内部問わず、取得あるいは代入されたときに呼び出されます。

 setterの引数は省略が可能で、newValueというデフォルト名を使うことも可能です。先ほどのCustomRangeクラスのendプロパティの宣言部分を略記法で書き換えると、次のようになります。

var end: Int {
get {
    return start + Int(length)
}
set {
    let newLength = newValue - start
    if newLength >= 0 {
        length = UInt(newLength)
    }
}
}

 setterは必須ではないため省略可能です。また、その場合には「get」と括弧も省略可能です。今度は、getterのみの計算プロパティcenterを追加してみましょう。

struct CustomRange {
    var start: Int = 0
    var length: UInt = 0
    var end: Int {
    get {
        return start + Int(length)
    }
    set(newEnd) {
        let newLength = newEnd - start
        if newLength >= 0 {
            length = UInt(newLength)
        }
    }
    }
    var center: Double {
        return Double(start + end) * 0.5
    }
}
var range = CustomRange()
range.end = 2
let center = range.center // 1.0

 

willSet/didSetによるプロパティ監視

 Objective-CでもKVO(Key-Value-Observing)という機構を用いれば、プロパティの値を監視することができました。Swiftではプロパティ値がsetされる直前あるいは直後のタイミングをwillSet/didSet構文で取得できます。

 次の例では、lengthプロパティに値がsetされる直前に「length will change」、setされた直後に「length did change」と出力されます。

struct CustomRange {
    var start: Int = 0
    var length: UInt = 0 {
    willSet {
        if length != newValue {
            println("length will change")
        }
    }
    didSet (newLength) {
        if length != newLength {
            println("length did change")
        }
    }
    }
}
var range = CustomRange()
range.length = 1
// length will change
// length did change

 ただし、イニシャライザでのプロパティ呼び出しのタイミングは取得できませんので、注意してください。

次のページ
メソッド

この記事は参考になりましたか?

アップルの新プログラミング言語「Swift」を探検しよう連載記事一覧

もっと読む

この記事の著者

yad(ヤド)

クラスメソッド株式会社のアプリケーションエンジニア。iPhoneアプリケーションの開発に2年以上従事している。開発に使用するObjective-Cのみならず、関数型言語Haskellや機械学習などにも関心がある。「Developers.IO」に寄稿した記事の一覧

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/7898 2014/08/09 21:40

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー