Chapter 20 - Challenge A -Page 271
Extra () in Item protocol definition should be:
protocol Item {
var name: String { get }
var clearance: Bool { get }
var msrp: Float { get }
func totalPrice() â Float
}
also the solution file uses a Double instead of a Float
Solution for Chapter 20 - Challenge A
The solution has a lot of errors in it:
Specifically:
Clothing(name: "Shirt", msrp: 12.99, clearance: true).totalPrice()
returns $12.99 when it should have adjusted the price to $9.74
The reason for this error is because it is using the totalPrice function from the Item protocol and wasnât overriden with the extension that required the struct have both TaxableItem and ClearanceableItem protocols.
Here is a version I came up with that cleaned up the errors, and I think helps demonstrate the concepts from the chapter:
import Foundation
// Item Protocol
protocol Item: CustomStringConvertible {
var name: String { get }
var msrp: Double { get }
func totalPrice() -> Double
}
extension Item {
func totalPrice() -> Double {
return msrp
}
}
extension Item {
var description: String {
let stringMsrp = String(format: "$%.2f", msrp)
var _description = "\(name) - \(stringMsrp)"
if let e = self as? ExpirableItem {
_description += e.expirableDescription
}
if let c = self as? ClearanceableItem {
_description += c.clearanceableDescription
}
return _description
}
}
// ClearanceableItem Protocol
protocol ClearanceableItem: Item {
var clearance: Bool { get set }
var discount: Double { get }
var adjustedMsrp: Double { get }
}
extension ClearanceableItem {
var adjustedMsrp: Double {
return msrp * (clearance ? (1 - discount) : 1.0)
}
var clearanceableDescription: String {
let stringAdjustedMsrp = String(format: "$%.2f", adjustedMsrp)
return clearance ? " -> ON SALE! Now just \(stringAdjustedMsrp)" : ""
}
func totalPrice() -> Double {
return adjustedMsrp
}
}
// TaxableItem Protocol
protocol TaxableItem: Item {
var salesTaxPercent:Double { get }
}
extension TaxableItem {
var salesTaxPercent: Double {
return 0.075
}
func totalPrice() -> Double {
return msrp + msrp*salesTaxPercent
}
}
extension TaxableItem where Self:ClearanceableItem {
func totalPrice() -> Double {
return adjustedMsrp + adjustedMsrp*salesTaxPercent
}
}
// Clothing Struct
struct Clothing: ClearanceableItem {
let name: String
let msrp: Double
var clearance: Bool
let discount = 0.25
}
// Electronic Struct
struct Electronic: TaxableItem, ClearanceableItem {
let name: String
let msrp: Double
var clearance: Bool
let discount = 0.05
}
// ExpirableItem Protocol
protocol ExpirableItem: Item {
var expirationMonth:Int {get}
var expirationYear:Int {get}
}
extension ExpirableItem where Self: Item {
var expirableDescription: String {
return " expires \(expirationMonth)/\(expirationYear)"
}
}
// Food Struct
struct Food: ClearanceableItem, TaxableItem, ExpirableItem {
let name: String
let msrp: Double
var clearance: Bool
let expirationMonth: Int
let expirationYear: Int
let discount = 0.5
}
Food(name: "Bread", msrp: 2.99, clearance: false, expirationMonth: 11, expirationYear: 2016).totalPrice()
Food(name: "Old Bread", msrp: 2.99, clearance: true, expirationMonth: 11, expirationYear: 2016).totalPrice()
Clothing(name: "Shirt", msrp: 12.99, clearance: false).totalPrice()
Clothing(name: "Last season shirt", msrp: 12.99, clearance: true).totalPrice()
Electronic(name: "Apple TV", msrp: 139.99, clearance: false).totalPrice()
Electronic(name: "Apple TV 3rd gen", msrp: 99.99, clearance: true).totalPrice()
//// Custom string convertible demonstration
Food(name: "Bread", msrp: 2.99, clearance: false, expirationMonth: 11, expirationYear: 2016)
var e = Electronic(name: "Apple TV 3rd gen", msrp: 99.99, clearance: false)
// Show the impact of changing the clearance flag
e.totalPrice()
e.clearance = true
e.totalPrice()