Harsh
Harsh

Reputation: 2908

Protocol Oriented Programming Example not working in swift 3.0

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

Answers (1)

Rob
Rob

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

Related Questions