Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

Swiftの「クラス」と「ストラクチャ」 その② ~ subscript、タイプキャスト、メモリ管理(およびクラス、ストラクチャ、列挙型のおさらい)

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

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2014/09/29 14:00

 前回はクラスとストラクチャを中心にプロパティ、メソッド、継承、ライフサイクルの解説をしました。今回はsubscript、アクセス修飾子、タイプキャスト、ARCによるメモリ管理を中心に解説した後、クラス、ストラクチャ、列挙型のおさらいをします。

目次

subscriptキーワード

 本連載第1回で取り上げたArray、Dictionaryには、次のように [] で中身にアクセスしたり更新したりする機能が備わっていました。

var animals = ["dog", "cat", "elephant"] // [String]
animals[1] // "cat"を取得
var countries = ["JPN" : "Japan", "USA" : "America"] // [String: String]
countries["USA"] = "United States" // "USA"のキーに対応する値を更新

 この機能をsubscriptといいます。自分で作成した型にsubscriptを宣言することでArrayのような[]を通じての中身のアクセスや更新の機能をカスタマイズすることができます。また、[]に入れる中身の型を変えることでsubscriptのオーバーロードを行うことも可能です。

 subscriptの宣言方法は、プロパティのget/setとメソッドを組み合わせたような構文をとります。

subscript(引数のリスト) -> 返り値 {
    get {
        文
        return 返り値
    }
    set(新たな値) {
        新たにセットされた値を元に計算
    }
}

 宣言の例を見てみましょう。

struct Page {
    let numberOfLines: Int
    let numberOfCols: Int

    private var contents: [String]

    init (numberOfLines: Int, numberOfCols: Int) {
        self.numberOfLines = numberOfLines
        self.numberOfCols = numberOfCols
        let emptyLine = String(count: numberOfCols, repeatedValue: " " as Character)
        self.contents = Array(count:numberOfLines, repeatedValue:emptyLine)
    }

    subscript(line: Int) -> String {
        get {
            return contents[line]
        }
        set (newLineContent) {
            let newContentCols: Int = countElements(newLineContent)
            if newContentCols <= numberOfCols {
                let newLine = newLineContent + String(count:numberOfCols - newContentCols, repeatedValue:" " as Character)
                contents[line] = newLine
            }
        }
    }
}

var somePage = Page(numberOfLines: 4, numberOfCols: 10)
somePage[1] // "          "
somePage[1] = "content"
somePage[1] // "content   "

 このサンプルコードは本のページを表したもので、行数と1行に入る文字数を指定できます。

 subscriptキーワードの後にはメソッドの引数リストと、返り値の宣言のように [] の中に渡したい引数の型のリスト、および代入と取得をしたい型を記述します(private修飾子は次の節で解説します)。 その後で、計算プロパティのget/setの宣言のように、getとsetで取得時および代入時の操作を記述します。

 なお、この例では [] の中で引数を1つしか渡していませんが、次のようにsubscriptを宣言することで、引数を2つ渡すこともできます。

struct Book {
    let name: String
    let numberOfPages: Int
    let numberOfLines: Int
    let numberOfCols: Int

    private var contents: [Page]

    init (name: String, numberOfPages: Int, numberOfLines: Int, numberOfCols: Int) {
        self.name = name
        self.numberOfPages = numberOfPages
        self.numberOfLines = numberOfLines
        self.numberOfCols = numberOfCols

        let emptyPage = Page(numberOfLines: numberOfLines, numberOfCols: numberOfCols)
        self.contents = Array(count:numberOfPages, repeatedValue:emptyPage)
    }

    subscript(page: Int, line: Int) -> String {
        get {
            return contents[page][line]
        }
        set {
            contents[page][line] = newValue
        }
    }
}

var someBook =
Book(name: "some",
    numberOfPages: 4,
    numberOfLines: 40,
    numberOfCols: 20)

someBook[1, 2] // "                    "
someBook[1, 2] = "p one l2 content"
someBook[1, 2] // "p one l2 content    "

 このサンプルコードは本を表したもので、本の名前とページ数、およびページの行数と1行に入る文字数を指定できます。

 subscriptは、Optional列挙型を返すときにはメソッドのようにみなして、オプショナルチェイニング[1]することも可能です。

struct BookShelf {
    private var books: [String: Book]
    init (books: Book...) {
        var bookDict: [String: Book] = Dictionary()
        for book in books {
            bookDict[book.name] = book
        }
        self.books = bookDict
    }

    subscript(name: String) -> Book? {
        return books[name]
    }
}

var bookShelf = BookShelf(books: someBook)
bookShelf["some"]?[1, 2] // "p one l2 content    "
bookShelf["any"]?[1, 2]  // nil

 このサンプルコードは本棚を表したもので、本の名前をキーにして本を貯めこむことができます。

[1] オプショナル列挙型を返すメソッドやプロパティを「.」(ピリオド)つなぎで次々に呼び出していくことです。「.」の前に「?」を置くことでそれが可能になります。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • yad(ヤド)

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

バックナンバー

連載:アップルの新プログラミング言語「Swift」を探検しよう
All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5