Skip to content

Instantly share code, notes, and snippets.

@fujikky
Last active January 6, 2016 05:13
Show Gist options
  • Save fujikky/c9dc6ac30d3c589dad0f to your computer and use it in GitHub Desktop.
Save fujikky/c9dc6ac30d3c589dad0f to your computer and use it in GitHub Desktop.
Swiftでサブクラスかつプロトコルに準拠してるオブジェクトへのキャストはどうやるの…
import Foundation
// 生物クラス
class Animal {
func run() {
}
}
// 名前を返すプロトコル
protocol Naming {
func name() -> String
}
// 人間クラス
class Human: Animal, Naming {
func name() -> String {
return "tarou"
}
}
// ペットクラス
class Pet: Animal, Naming {
func name() -> String {
return "pochi"
}
}
// 野生生物クラス
class Wildlife: Animal {
}
// 生物のインスタンスをランダムに返す
func randomAnimal() -> Animal {
switch arc4random() % 3 {
case 0: return Human()
case 1: return Pet()
default: return Wildlife()
}
}
// ここからコンパイルエラー
// run() と name() を両方実行できる型にキャストしたい
let animal = randomAnimal() // as Animal
animal.run()
animal.name() // コンパイルエラー: Value of 'Animal' has no member 'name'
if let namingObj = randomAnimal() as? Naming {
namingObj.run() // コンパイルエラー: Value of 'Naming' has no member 'run'
namingObj.name()
}
if let namingAnimal = randomAnimal() as? Animal<Naming> { // コンパイルエラー: Cannot specialize non-generic type 'Animal'
namingAnimal.run()
namingAnimal.name() // コンパイルエラー: Value of 'Animal' has no member 'name'
}
@jarinosuke
Copy link

let animal = randomAnimal()
animal.run()
if animal is Naming {
    (animal as! Naming).name()
}

手っ取り早いのはこれですかねー。

@fujikky
Copy link
Author

fujikky commented Jan 6, 2016

わーありがとうございます!なるほど、この実装だと両メソッドが実行可能な型の変数に収めるのはできないんですねー

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment