あるコンテナのキャッシュのためにDictionaryを使っていたとき、
できるだけI/F側がゴチャゴチャしにくい方法を考えていたら
protocol を extension することで解決できたので共有しておきます。
var dict:[String:UIView] = [:]
func fuga(key:String, view:UIView){
dict[key] = view
}
// 文字列以外がすんなり入らない。
fuga("text", view: UIView())
fuga(1, view: UIView()) // コンパイルエラー
fuga(1.2, view:UIView()) // コンパイルエラー
// こうすれば入るけど、面倒
fuga(String(1), view: UIView())
fuga(String(1.2), view:UIView())
// クラスの場合はどうしよう
class Profile {
var fistName:String
var lastName:String
var age:Int
init(first:String, last:String, age:Int){
self.fistName = first
self.lastName = last
self.age = age
}
}
fuga(Profile(first: "m", last: "k", age: 30), view:UIView()) // コンパイルエラー
Stringを返させるプロトコルにする
protocol Key {
var Name:String { get }
}
func hoge(key:Key, view:UIView){
dict[key.Name] = view
}
// プロトコルを採用したものじゃないといけなくなったので、文字列よりひどくなる
hoge("text", view: UIView()) // コンパイルエラー
hoge(1, view: UIView()) // コンパイルエラー
hoge(1.2, view:UIView()) // コンパイルエラー
hoge(Profile(first: "m", last: "k", age: 30), view:UIView()) // コンパイルエラー
protocol extension を使って、String,Int,Doubleといったプリミティブ型を始めクラスのデフォルト行動を定義する
extension String : Key{
var Name: String{get{return self}}
}
extension Int : Key{
var Name: String{get{return String(self)}}
}
extension Double : Key{
var Name: String{get{return String(self)}}
}
extension Profile : Key{
var Name: String{get{return String("\(self.fistName)\(self.lastName)\(self.age)")}}
}
// これなら通る
hoge("text", view: UIView())
hoge(1, view: UIView())
hoge(1.2, view:UIView())
hoge(Profile(first: "m", last: "k", age: 30), view:UIView())