2016年03月24日

Swift: conformProtocol()、respondsToSelector:


Objective-Cでプロトコルに対応しているかどうかを判定するconformProtocol関数や、メソッドを持っているかどうかを調べるrespondsToSelectorのSwiftでの代替について。

ただし、Objective-Cとは違いSwiftでは静的な型の決定を行っているのでほとんどがコンパイル時に決定でき、動的に判定することはない。というかそのような使い方は避けるべきと考えられる。

ここではごく基本的なものを示す。個別の事情によりまた別の判定方法を使った方がよいことがあるので、それらはいつか実際の事例毎にまとめたい。

まず、準備として1つのプロトコルと4つの親子関係にないクラスを定義する。Swiftでは非形式プロトコルは認められない。また、オプションメソッドも存在しない。Objective-Cのクラスをインポートして使う場合のみにオプションメソッドが使えるので下記のような定義となる。

プロトコルに対応しない2つのクラスと、プロトコルに対応する2つのクラスを定義。それぞれ一方にはプロトコルのオプショナルメソッドと同名のメソッドを定義する。

import Foundation

@objc protocol MyProtocol {
optional func someMethod()
}

class MyClass {

}

class AnotherClass {
func someMethod() {
print("someMethod() in AnotherClass")
}
}

class ClassWithProtocol : MyProtocol {

}

class GoodClass : MyProtocol {
@objc func someMethod() {
print("someMethod() in GoodClass")
}
}


Objective-Cとの違いは同名のメソッドであってもプロトコルを実装していないクラスでは同じメソッド扱いになっていないということ。

SwiftでもSelector("someMethod")のような記法でセレクタを定義できるが、これはObjective-Cのクラスがセレクタを要求する場合にのみ使える。Swiftの側で独自にこのメソッドを呼び出す方法はない。私が見つけられていないだけかもしれないけど。

プロトコルに対応しているかどうかの判定は as? で行う。メソッドを実装しているかどうかは、メソッドを代入する方法で確認できる。

よく使うのはdelegate関数がメソッドを実装しているかどうかだが、それも同様。

let myClass = MyClass()
let anotherClass = AnotherClass()
let classWithProtocol = ClassWithProtocol()
let goodClass = GoodClass()
let array: [AnyObject] = [
myClass, anotherClass, classWithProtocol, goodClass,
]
for object in array {
if let object = object as? MyProtocol {
print("\(String(object.dynamicType)) has MyProtocol.")
}
if let theMethod = object.someMethod {
theMethod()
}
}

var delegate: MyProtocol?
delegate = classWithProtocol
if let theMethod = delegate?.someMethod {
theMethod()
}
delegate = goodClass
if let theMethod = delegate?.someMethod {
theMethod()
}


実行結果の出力は以下。

ClassWithProtocol has MyProtocol.
GoodClass has MyProtocol.
someMethod() in GoodClass
someMethod() in GoodClass
posted by 永遠製作所 at 00:47| 東京 ☀| Comment(0) | TrackBack(0) | Swift | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

※ブログオーナーが承認したコメントのみ表示されます。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/435541440
※ブログオーナーが承認したトラックバックのみ表示されます。
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック