Swiftで特定のクラスの配列にファンクションを追加する

Swiftで特定のクラスの配列にファンクションを追加する

皆さんこんにちは

毎週火曜日に行っている南青山のSwiftもくもく勉強会の「青南.swift もくもく勉強会 第9回」を開催しました。
今日は、普段書いているコードがどういう仕組みになっているのか、PlayGroundで検証してみました。

ちなみに次回のイベントは既に公開してます。
青南.swift もくもく勉強会 第10回

検証環境

  • macOS Sierra Version 10.12.3
  • XCode 8.2.1
  • Swift 3.0.2

Swiftで特定のクラスの配列にファンクションを追加する

以下の例では、ProgrammingLanguageというクラスの配列に、find(byId:)と、find(byName:)というファンクションを実装しています。

class Language {
    var id: Int
    var name: String
    
    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }
}

class ProgrammingLanguage: Language {
}

class NaturalLanguage: Language {
}

// Arrayにファンクションを追加
extension Array where Element: ProgrammingLanguage {
    func find(byId id: Int) -> ProgrammingLanguage? {
        if let index: Int = map({ $0.id }).index(of: id) {
            return self[index]
        } else {
            return nil
        }
    }
    
    func find(byName name: String) -> ProgrammingLanguage? {
        if let index: Int = map({ $0.name }).index(of: name) {
            return self[index]
        } else {
            return nil
        }
    }
}

// テスト出力
let programingLanguages: [ProgrammingLanguage] = [
    ProgrammingLanguage(id: 1, name: "Ruby"),
    ProgrammingLanguage(id: 2, name: "Java"),
    ProgrammingLanguage(id: 3, name: "Objective-C"),
    ProgrammingLanguage(id: 4, name: "Swift"),
    ProgrammingLanguage(id: 5, name: "Go")
]

let naturalLanguages: [NaturalLanguage] = [
    NaturalLanguage(id: 1, name: "English"),
    NaturalLanguage(id: 2, name: "Japanese")
]


programingLanguages.find(byName: "Ruby")?.name
programingLanguages.find(byId: 2)?.name

当然NaturalLanguageやその他のProgrammingLanguage以外の配列では使えません。

どのような仕組みか

以下のように、Arrayのエクステンションとして実装しています。
whereを使うことによって、ElementがProgrammingLanguageの場合だけ使えるようになります。

extension Array where Element: ProgrammingLanguage {

ここで指定しているElementというのはArrayに格納されているオブジェクトの型を現しているジェネリクスです。

Arrayの定義は以下のようになっています。

public struct Array<Element> : RandomAccessCollection, MutableCollection {

whereで型を指定することにより、ArrayのElement(格納されているオブジェクト)がProgrammingLanguageの場合、ファンクションが実行できるようになります。

TAG

  • このエントリーをはてなブックマークに追加
金子 将範
エンジニア 金子 将範 rubyist

新しいことや難しい課題に挑戦することにやりがいを感じ、安定やぬるい事は退屈だと感じます。 考えるより先に手が動く、肉体派エンジニアで座右の銘は諸行無常。 大事なのは感性、プログラミングにおいても感覚で理解し、感覚で書きます。