這裏有一種方法我可以做到這一點:
- 聲明一個
protocol AnimalType
。在它裏面,定義一個動物是什麼,它可以做什麼,但不知道它是如何做的。這個命名約定使用遍佈雨燕標準庫:CollectionType
,SequenceType
,IntegerType
,BooleanType
等
- 聲明一個
class Animal
定義所有的動物怎麼辦,他們共同擁有的東西;對於其他任何東西,只需製作佔位符函數或屬性(這是您的「抽象」類)。如果你有一個功能對你的抽象類沒有任何意義,請在它的正文中調用fatalError()
。
- 根據需要創建您的具體
class Dog
,class Bird
等和override
功能和/或添加新功能。
事情是這樣的:
struct Leg { } // Just so it'll run in a Playground
protocol AnimalType: class {
func run()
var legs : [Leg] { get }
func legCount() -> Int
}
class Animal: AnimalType {
func run() {
fatalError("run() can not be called on the Animal class")
}
var _legs: [Leg]! = nil
var legs: [Leg] { get { return _legs } }
func legCount() -> Int {
return legs.count
}
}
class Dog: Animal {
override func run() {
println("Running Dog!")
}
override init() {
super.init()
_legs = [Leg](count: 4, repeatedValue: Leg())
}
}
class Bird : Animal {
override func run() {
println("Running Bird!")
}
override init() {
super.init()
_legs = [Leg](count: 2, repeatedValue: Leg())
}
}
然後,如果你需要說動物的Array
,使用協議聲明數組,而不是Animal
類:
let animals: Array<AnimalType>
嘗試一些東西out:
let dog = Dog()
println("Dogs have \(dog.legCount()) legs.")
dog.run()
let bird = Bird()
println("Birds have \(bird.legCount()) legs.")
bird.run()
將輸出:
Dogs have 4 legs.
Running Dog!
Birds have 2 legs.
Running Bird!
的Array
也可以工作:
var animals: Array<AnimalType> = [dog, bird]
var legs = animals.map { $0.legCount() }
println(legs)
[4, 2]
而且,雖然Animal
仍然可以實例:
let a = Animal()
調用run()
上這將是一個致命錯誤:
a.run()
fatal error: run() can not be called on the Animal class: file <EXPR>, line 18
擁有'AnimalType'協議有什麼好處? – 2014-10-29 04:27:00
IE,你可以使用'let animals:[動物] = ...',我不認爲你會因此而失去任何東西。 – 2014-10-29 04:38:01
@AaronBrager true,'[動物]'會工作得很好。一般來說,我會說它允許實現相同協議的不同基類。具體而言,在這種情況下,可能沒有太多意義。 – 2014-10-29 04:58:13