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の場合、ファンクションが実行できるようになります。

    この記事はいかがでしたか?

    writer
    金子 将範
    金子 将範

    スペシャリスト

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

    関連記事

    ページトップへ