くま's Tech系Blog

基本的には技術で学んだことを書き留めようと思います。雑談もやるかもね!

extensionとprotocolについて

今回はiOSでよく使うextensionとprotocolについて記載しようと思います

extensionについて

Swiftでは既存のStringやArrayなど提供されているクラス(既存のクラス)に自分専用のメソッドを追加できます。

Objective-Cにはカテゴリという、既存クラスにメソッドを追加できる機能がありますが、カテゴリで追加できるのはクラスのみに限定されています。

なので、これはかなり便利ですね。たまにこの機能欲しいってなったときにStringやArrayをいじることなく追加ができてしまいます。

例えを見ていきましょう!!

import Foundation
extension String {
 //メンバ変数のhogeを追加
    func helloWorld()->String{
        return "Hello World!!";
    }
}

上記のhelloWorld関数を追加するだけでString型の処理でhelloWorld関数を使えます

定義の仕方は、既存のファイルに追加や新しいファイルを作成するという手順です。

protocolについて

protocolは色んな言語でいうインターフェースです。

つまり、継承したクラスで実装すべきプロパティやメソッドを宣言する為に利用します。

Javaを使っていた自分としてはインターフェースと知ってから一気にイメージが湧きました。

使い方としては下記のようなプロトコルを用意します。

protocol TestProtocol
{
    var Test:String {get set}
    
    func  Test() -> Void
}

そして、下記のように継承・プロトコル実装します。

class Test : TestProtocol
{
    var test:String!
    
    // 実装しないとエラーになる
    var Test1: String
    {
        get
        {
            return self.test
        }
        set
        {
            self.test = newValue
        }
    }
    
    // 実装しないとエラーになる
    func  Test() -> Void{
        print(self.Test1)
    }
}

こうすることで、プロトコルで宣言されたメソッドを継承クラスで利用できます。

var test1:TestProtocol= Test()

test1.Test1 = "テスト"
test1.Test() // テスト

その他に、viewControllerでも使うパターンがあります。

class TestViewController: UIViewController { 
    self.tableView.delegate = self 
    self.tableView.dataSource = self 
    self.webView.delegate = self 
} 

extension TestViewController: UITableViewDataSource {
    ... 
} 

extension TestViewController: UIWebViewDelegate { 
    ... 
}

このようにすると、どのパターンでどんな処理を行うのか一気に見やすくなります。

getter/setterとプロトコルで定義したメソッドは継承先で記述しないとエラーになります。(どの言語でも同じだとは思いますが)

依存性を減らすことができるので、柔軟性が高くて抽象化できるのがメリットだと思います。

extensionとprotocolの組み合わせ

最後に、extensionとprotocolを組み合わせるパターンを紹介します。

ここでは動物プロトコルを定義しています。

protocol Animal {
    var name: String { get }
    func bark() -> String
}

動物インターフェースを下記のように作成します。

struct Cat: Animal {
    let name = "ぽち"
    func bark() -> String {
        return "ワン"
    }
}

let cat = Cat()
cat.name          // "ぽち"
cat.bark()        // "ワン"

動物インターフェースではProtocol で宣言した変数・関数を実装すれば犬がの名前と鳴き声を設定できます。

ただ毎回鳴き声を実装するのが大変な場合があります。基本的に動物が鳴かないのであればデフォルトで空白を入れればいいですね。

extension Animal {
    func bark() -> String {
        return ""
    }
}

このようにextensionとprotocolを組み合わせることで冗長な処理を書かなくて済むことが多いです。

基本的な内容になりましたが、よく使うと思うので参考にしてみてください

参照

SwiftのProtocol(プロトコル)とextension(エクステンション)

【Swift】Extensionしてますか?