Swift

swiftのプロトコル

プロトコルを使うメリット

  • Protocol Extension で見通しの良いコードになる。
  • 複数適用できる
  • 柔軟性が高い

もちろんデメリットもある。

基本

  • 多言語でいうインターフェース
  • classやstructやenumなどで使える。
  • 複数適用可能
  • @objc optional なメソッドを定義できる
  • デリゲートで使う

Extensionで読みやすく

protocol SomeProtocol {

    func methodA()

    func methodB(_ str: String)

    func methodC(a: Int, b: Int) -> Int
}
class someClass {
}

extension someClass: SomeProtocol {

    func methodA() {
    }

    func methodB(_ str: String) {
        print(str)
    }

    func methodC(a: Int, b: Int) -> Int {
        return a+b
    }
}

let s = someClass()

s.methodA()  //do nothing
s.methodB("hello world") // hello world
s.methodC(a: 2, b: 5) // 7

こんな感じで書けるので凄く見やすい、てかほとんどこれがしたいだけです。
Xcodeだと補完がサクサク出てくるので楽チンです。
tableViewのDelegateとかもこうやって分けて書きます。

メソッド定義

下のようにextensionで定義したメソッドはSomeProtocolを適用した全てのクラスが使えます。

protocol SomeProtocol {
}

extension SomeProtocol {
    func sayHoge() {
        print("hoge")
    }
}
class someClass: SomeProtocol {
}

let s = someClass()
s.sayHoge() // hoge

someClassはsomeProtocolを適用しているので
"hoge"って言ってくれます。

プロパティ

protocol SomeProtocol {

    var name: String { get }
}

extension SomeProtocol {

    func sayHello() {
        print("Hello \(name)!")
    }
}
class SomeClass{
}

extension SomeClass: SomeProtocol {

    var name: String {
        return "Bob"
    }
}

let s = SomeClass()
print(s.name) //Bob
s.sayHello() //Hello Bob!

このように直接プロパティーを持つことはできないのですが、それっぽく使うことができます。

普通に配列に入れられます

protocol SomeProtocol {
}

extension SomeProtocol {

    func className() {
        print(String(describing: type(of: self)))
    }
}

class someClassA: SomeProtocol {
}

class someClassB: SomeProtocol {
}

class someClassC: SomeProtocol {
}

let a = someClassA()
let b = someClassB()
let c = someClassC()

let someArray: [SomeProtocol] = [a,b,c]

for s in someArray {
    s.className()
}
someClassA
someClassB
someClassC

骨組みだらけでわかりにくい・・・

型制約

特定のクラスにのみ使えるメソッドを定義できます

protocol SomeProtocol: class {
}

extension SomeProtocol {
    func sayHello() {
        print("hello")
    }
}

extension SomeProtocol where Self: SomeClass  {

    func someMethod(){
        print("instance of SomeClass can use this method")
    }
}
class SomeClass: SomeProtocol {
}

class OtherClass: SomeProtocol {
}

let s = SomeClass()
s.sayHello() //hello
s.someMethod() //instance of SomeClass can use this method

let o = OtherClass()
o.sayHello() //hello
o.someMethod() // error: 'OtherClass' is not a subtype of 'SomeClass'

associatedtype

NSObjectを拡張してみる


protocol Extensible {

    associatedtype ExtensibleType

    static var ex: Extension<ExtensibleType>.Type { get }

    var ex: Extension<ExtensibleType> { get }
}

extension Extensible {

    public static var ex: Extension<Self>.Type {
            return Extension<Self>.self
    }

    public var ex: Extension<Self> {
        return Extension(self)
    }
}


public struct Extension<Base> {

    public let base: Base

    public init(_ base: Base) {
        self.base = base
    }
}

extension NSObject: Extensible {}

swiftが柔軟なためほぼ共通処理はBaseClassのようなものを作らなくてもプロトコルで十分対応できますので気が向いたら使って見てください。
個人的にはクラスに武器を装備させるような感じで楽しいです。
授業中暇なので書いてみました。