Here's one way I might do it:
- Declare a
protocol AnimalType. In it, define what an animal is and what it can do, but not how it does anything. This naming convention is used all over the Swift standard library: CollectionType, SequenceType, IntegerType, BooleanType, etc.
- Declare a
class Animal that defines how all animals do the things that they have in common; for everything else, just make placeholder functions or properties (this is your "abstract" class). If you have a function that doesn't make sense to call on your abstract class, call fatalError() in it's body.
- Create your specific
class Dog, class Bird, etc. and override functions and/or add new ones as needed.
Something like this:
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())
}
}
Then, if you need say an Array of animals, declare the array using the protocol, not the Animal class:
let animals: Array<AnimalType>
Trying some stuff out:
let dog = Dog()
println("Dogs have \(dog.legCount()) legs.")
dog.run()
let bird = Bird()
println("Birds have \(bird.legCount()) legs.")
bird.run()
Which will output:
Dogs have 4 legs.
Running Dog!
Birds have 2 legs.
Running Bird!
The Array also works:
var animals: Array<AnimalType> = [dog, bird]
var legs = animals.map { $0.legCount() }
println(legs)
[4, 2]
And, while Animal can still be instantiated:
let a = Animal()
Calling run() on it will be a fatal error:
a.run()
fatal error: run() can not be called on the Animal class: file <EXPR>, line 18