Reputation: 2908
I have the following piece of code where am trying to implement my Zoo example using Structs
and Protocols
.
In the example, I have a Zoo where there is certain type of animals which have a certain type of characteristics. Details of the question are in the Readme file of repo (https://github.com/harsh62/Melbournce-Zoo/blob/master/README.md)
I want to understand whether what am trying to do is the correct approach or not? The following piece of code compiles without any errors but doesn't work.
Can somebody help, please?
enum Sex {
case Male
case Female
case Other
}
enum Size:Int {
case ExtraSmall = 0
case Small = 1
case Medium = 2
case Large = 3
case ExtraLarge = 4
}
enum Diet {
case Herbivore
case Carnivore
}
protocol Animal {
var sex: Sex { get set }
var size: Size { get set }
var diet: Diet { get set }
var weight: Double { get set }
var age: Int { get set }
}
protocol Swimmable {
var swimSpeed: Double { set get }
}
protocol NeedsEclosure {
func enclosureSize() -> Double
}
protocol Carnivorous {
func meatSize() -> Double
}
protocol Mammal { }
protocol Fish {
var adjustedSpeed: Double { set get }
}
protocol Bird { }
protocol Reptile { }
protocol Invertebrate { }
/////Extensions to protocols
extension Animal {
var weight: Double {
set {
self.weight = newValue
}
get {
return weight
}
}
var age: Int{
set {
self.age = newValue
}
get {
return age
}
}
var size: Size{
set {
self.size = newValue
}
get {
return size
}
}
var diet: Diet{
set {
self.diet = newValue
}
get {
return diet
}
}
var sex: Sex{
set {
self.sex = newValue
}
get {
return sex
}
}
}
extension Swimmable {
var swimSpeed: Double{
set {
self.swimSpeed = newValue
}
get {
return swimSpeed
}
}
}
extension NeedsEclosure where Self: Animal {
func enclosureSize() -> Double {
return Double(size.rawValue) * weight
}
}
extension Carnivorous where Self: Animal {
func meatSize() -> Double {
return Double(size.rawValue) * weight
}
}
extension Swimmable where Self: Animal {
var adjustedSpeed: Double { return (swimSpeed/weight)/Double(age) }
}
/////////////////////////////////
typealias BigCat = Animal & Mammal & Swimmable & Carnivorous & NeedsEclosure
struct Tiger: BigCat { }
var tiger = Tiger()
tiger.enclosureSize()
Upvotes: 0
Views: 135
Reputation: 437882
Your extension
of Animal
where you define all of those computed properties makes no sense. You need stored properties. It makes no sense for a computed getter, weight
for example, to return weight
. Likewise, the computed setter, self.weight = weight
doesn't make sense.
You need stored properties to store all of these values, and stored properties cannot be implemented in a protocol extension. Consider your protocol for Animal
:
protocol Animal {
var sex: Sex { get set }
var size: Size { get set }
var diet: Diet { get set }
var weight: Double { get set }
var age: Int { get set }
}
You really need to hold all these values somewhere, you can't use computed properties defined in a protocol extension. (So get rid of that extension
for Animal
that defines those invalid computed properties.) You actually want to implement these stored properties inside the type that conforms to this protocol, e.g.:
typealias BigCat = Animal & Mammal & Swimmable & Carnivorous & NeedsEnclosure
struct Tiger: BigCat {
var swimSpeed = 2.0
var size = Size.large
var sex = Sex.male
var diet = Diet.carnivore
var weight = 400.0
var age = 4
}
(By the way, I changed the values of those various enum
types to use lowercase letter, as is the convention in Swift 3.)
Your protocol extensions can provide default implementations for methods and computed properties, but not for stored properties.
Upvotes: 2