NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

SOLVED: Checkpoint 8 | Is this complete?

Forums > 100 Days of SwiftUI

Hello this is my solution to checkpoint 8, but I am not sure if I covered everything and I don´t have HWS+. Is there something I misunterstood or else? Sometimes I have problems to understand the task (I am German btw).

The extension was just a experiment.

protocol Building {
    var rooms: Int { get }
    var price: Int { get }
    var agent: String { get }
    func salesSummary()
}

struct House: Building {
    var rooms: Int
    var price: Int
    var agent: String

    func salesSummary() {
        print("Here we have a beautiful House with \(rooms) rooms. The price will be \(price) Dollars and your agent is \(agent)")
    }
}

extension House {
    init(rooms: Int, agent: String) {
        self.rooms = rooms
        self.price = rooms * 50_000
        self.agent = agent
    }
}

struct Office: Building {
    var rooms: Int
    var price: Int
    var agent: String

    func salesSummary() {
        print("Here we have a beautiful Office with \(rooms) rooms. The price will be \(price) Dollars and your agent is \(agent)")
    }
}

let house = House(rooms: 6, price: 150_000, agent: "Maxi")
house.salesSummary()

let office = Office(rooms: 2, price: 50_000, agent: "Maxi")
office.salesSummary()

let extHoues = House(rooms: 5, agent: "Maxi")
extHoues.salesSummary()

1      

I think your solution ist wunderbar.

But you ask if you covered everything. I changed your solution a bit, so you might have a deeper understanding.

protocol Building {
    var rooms: Int { get }  // Why is this a var, if you specify you can only GET this value? Should it be a let?
    var price: Int { get }
    var agent: String { get }
    func salesSummary()
}

Your protocol says when you implement this protocol, your struct MUST have a var that a programmer can get. In your House and Office struct, you implement this as a var rooms: Int

I changed the Office struct to make rooms a computed property. This still satisfies the protocol. Because you can certainly GET the value of rooms (the contract), but you cannot write a value for rooms.

struct Office: Building {
    var rooms: Int { // Number of rooms is computed based on number of seats in the office building.
        seats / 2     // Example only.  Each office contains 2 seats.
    }

    var seats: Int  // added this variable to report number of seats in the office building.
    var price: Int
    var agent: String

    func salesSummary() {
        print("Here we have a beautiful building with \(seats) seats in \(rooms) offices. ")
    }
}

The deeper understanding is that the protocol can be implemented as a standard var or as a computed property. Your choice!

3      

I'm done for today and already put my laptop away so I can't paste any code, but my first solution looked very similar to the OP, just maybe less dynamic for the lack of a better word, and without the cost calculations. I did think about calculating the price based on the number of rooms but was too tired (long day at work!) so maybe I'll have a shot at it tomorrow.

I've also misunderstood or missed something in the checkpoints a couple of times. My advice would be to read through them very carefully and at least twice before writing any code. And when your program is ready, read through the assignment again and compare the different requirements to different parts of your code.

2      

Hacking with Swift is sponsored by Stream

SPONSORED Build Chat messaging quickly with Stream Chat. The Stream iOS Chat SDK is highly flexible, customizable, and crazy optimized for performance. Take advantage of this top-notch developer experience, get started for free today!

Click here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Here's my new take on this checkpoint:

protocol RealEstate {
    var type:   String   { get }
    var rooms:  Int      { get }
    var roomPrice: Int   { get }
    var cost:   Int      { get }
    var agent:  String   { get }

    func summarize()
}

struct House: RealEstate {
    var type  = "residential"
    var rooms = 5
    var roomPrice: Int
    var cost: Int { get { rooms * roomPrice } }
    var agent = "Liz Ard"

    func summarize() {
        print("This house is a \(type) building with \(rooms) rooms. The price is \(cost) euros. If interested, please contact sales agent \(agent).")
    }
}

struct Office: RealEstate {
    var type  = "commercial"
    var rooms = 8
    var roomPrice: Int
    var cost: Int { get { rooms * roomPrice } }
    var agent = "Rep Tilian"

    func summarize() {
        print("AVAILABLE: \(type) space with \(rooms) rooms. The price is \(cost) euros. Contact sales agent \(agent) for more information.")
    }
}

let newHome = House(roomPrice: 12500)
newHome.summarize()

let newOffice = Office(roomPrice: 33000)
newOffice.summarize()

2      

my code was mostly similar to above answers

protocol Building {
    var rooms: Int {get}
    var cost: Int {get set}
    var agent: String {get}
    func summary ()
}

struct House: Building {
    var rooms: Int
    var cost: Int
    var agent = "HomeSeller"
    func summary (){
        print("the House price of the property with \(rooms) rooms is \(cost) which was sold by \(agent)")
    }
}

struct Office: Building {
    var rooms: Int
    var cost: Int
    var agent = "OfficeSeller"
    func summary (){
        print("the Office price of the property with \(rooms) rooms is \(cost) which was sold by \(agent)")
    }
}

extension House {

    init(room: Int) {
        self.rooms = room
        self.cost = room * 100
        }
    }

extension Office {

    init(room: Int) {
        self.rooms = room
        self.cost = room * 200
        }
    }

let H1 = House(room: 3)
let O1 = Office(room: 2)
H1.summary()
O1.summary()

1      

@alavijay No one answer is absolutely correct. Thanks for sharing. But may I ask a favor? Add a few comments to your code!

Let us know what parts are different, but to the point, share your thoughts. What was your approach to solving this assignment. We want to hear diverse thoughts and see other approaches.

1      

I had a very similar answer but I put the printSummary function in the protocol extension so that it only had to be written once:

protocol Building {
    var rooms: Int {get set}
    var cost: Int {get set}
    var agent: String {get set}
    var type: String {get set}
    func printSummary()
}

extension Building {
    func printSummary() {
        print("\(agent) is showing a \(rooms) room \(type) property that costs \(cost).")
        //by adding the print summary to the extension, it avoids having to write separate functions for each struct
    }
}

struct House: Building {
    var rooms: Int
    var cost: Int
    var agent: String
    var type: String = "residential"
}

struct Office: Building {
    var rooms: Int
    var cost: Int
    var agent: String
    var type: String = "commercial"
}

let house = House(rooms: 4, cost: 1_250_000, agent: "Sue Casa")
house.printSummary()

let office = Office(rooms: 12, cost: 12_000_000, agent: "Moe Dollas")
office.printSummary()

4      

I think the code is ok. But I have a doubt: Setting in a protocol a property to be only { get } does not enforce that it should be a constant property in the implementation (it allows it to be a variable that can be changed in runtime without complains from the compiler or runtime errors. Does any one know why? I don't see much use in using { get set} var in protocols when anyone defined as { get } behaves as one defined {get set}.

import Cocoa

protocol Building {
    var rooms: Int { get }  // hinting that rooms should be a constant
    var cost: Int { get set } // requiring that cost be a variable
    var agent: String { get set } // requiring that the agent be a variable

    func summary() // requiring a method named summary
}

// Extension defining a default implementation of the method summary for any struct
// or class build accordingly to protocol Building
extension Building {
    func summary() {
        print("Property with \(rooms) rooms and total cost of $\(cost)")
        print("Managed by: \(agent)")
    }
}

// Structure that complies with the implementation of protocol building
struct House: Building {
    let rooms: Int
    var cost: Int
    var agent: String
}

// Structure that seems to comply with the implementation of protocol building.
// DOUBT: The compiler doesn't complain when we define rooms as a var, eventhough
// we have stablished in the protocol that should be a constant.
struct Mansion: Building {
    var rooms: Int
    var cost: Int
    var agent: String
}

// Structure that complies with the implementation of protocol building
struct Office: Building {
    let rooms: Int
    var cost: Int
    var agent: String
    // Custom implementation of the method defined in the extension to protocol building
    func summary() {
        print("Property with \(rooms) rooms.")
        print("Managed by: \(agent)")
    }
}

// Implementing a custom Initializer for the House structure via extension.
// This way we still have the default initializer provided automatically by the structure
// and the custom one.
extension House {
    init(rooms: Int, cost: Int){
        self.rooms = rooms
        self.cost = cost
        self.agent = "Not assigned"
    }
}

// I don't get it. Why say in the protocol that var rooms = Int { get }
// if it does allow to define rooms as a var and in runtime it behaves as a var.
var myMansion = Mansion(rooms: 6, cost: 1100_000, agent: "john")
print(myMansion.rooms)
myMansion.rooms = 2
print(myMansion.rooms)

   

Alphonso shares his doubts:

Does any one know why?
I don't see much use in using { get set} var in protocols when
vars defined as { get } behave the same as vars defined {get set}.

Loose Implementation

Protocols define the required behavior. Other behaviors are optional. If you define a variable to be {get}, then you are telling the compiler that to conform a struct must at the very LEAST allow a progammer to get the value.

protocol FullName {
    // protocol says ensure programmer can GET fullName.
    // protocol doesn't require you to set publically, or privately.
    var fullName: String { get }
}

public struct PianoPlayer: FullName {
    // fullName can be set directly via public interface. (Optional behavior)
    public var fullName: String

    // fullName can be set via internal function (Optional behavior)
    mutating func changeName(newName: String) {
        fullName = newName
    }
    // fullName can be set via initializer
    public init(newName: String) {
        fullName = newName.uppercased()
    }
}

var pianoMan = PianoPlayer(newName: "B Joel")     // <- Set via initializer
print(pianoMan.fullName)                          // <- prints "B JOEL"
pianoMan.fullName = "Billy Joel"                  // <- Set var directly
print(pianoMan.fullName)                          // <- prints "Billy Joel")
pianoMan.changeName(newName: "Elton John")        // <- Set via method
print(pianoMan.fullName)                          // <- prints "Elton John")

Strict Implementation

In this example, the programmer implements the FullName protocol with stricter behaviors. Note, the protocol only requires the struct to allow a programmer to get the value. It doesn't specify how the var is set.

public struct Singer: FullName {
    // Implement the FullName protocol.
    // Implement stricter behavior regarding setting.
    // Protocol doesn't care, but I DO!
    // Prevent direct updating the fullName with private(set)
    public private(set) var fullName: String

    // Only internal functions can change the fullName variable.
    public mutating func renameWith(replacementName: String) {
        fullName = replacementName
    }

    public init(newName: String) {
        fullName = newName.uppercased()
    }
}

var swift = Singer(newName: "Taylor")               // <- Set via initializer
print(swift.fullName)                               // <- prints "Taylor"
swift.renameWith(replacementName: "Taylor Swift")   // <- Set via internal method
print(swift.fullName)                               // <- prints "Taylor Swift" to the console

// Attempt to set variable directly in code
swift.fullName = "Adele"                            // Error! Cannot assign to property: 'fullName' setter is inaccesible
print(swift.fullName)

Please note:
The protocol did not require fullName to have a private setter. The protocol only requires that the struct allows getting the value!

   

Alphonso! Forgot to mention!

I really appreciate how you documented your code. Nicely done, and complete!

50 points to Ravenclaw!

   

Thanks @Obelix.

   

Hm, I'm afraid that I didn't get that whole protocol topic, at least not for this task. I did it like that:

import UIKit

protocol Building {
    func summary(rooms: Int, cost: Int, agent: String)
}

struct House: Building {
    func summary(rooms: Int, cost: Int, agent: String) {
        print("""
                Rooms: \(rooms)
                Cost: \(cost)
                Agent: \(agent)
                """)
    }
}

struct Office: Building {
        func summary(rooms: Int, cost: Int, agent: String) {
            print("""
                    Rooms: \(rooms)
                    Cost: \(cost)
                    Agent: \(agent)
                    """)
        }
    }

let house = House()
house.summary(rooms: 5, cost: 500_000, agent: "Harry")

let office = Office()
office.summary(rooms: 6, cost: 600_000, agent: "Harry")

But yeah, removing the protocol completely would lead to the same result ...

   

@tomn  

I wanted to be able to do something clever with enum or dictionaries, by setting a building type like a code, and then print out a longform name in the sales summary, but didn't get to it.

enum BuildingType {
    case mansion, house, apartment, office
}

protocol Building {
    var rooms: Int { get set } // number of rooms to begin with. Option to add rooms.
    var cost: Int { get set } // cost or value. May change.
    var agent: String { get } // Agent will be a constant.
    var name: String { get } // Name of the property will be a constant.
    var type: BuildingType { get } // Type of the building. An enum.
    func printSalesSummary() // method to get sales report.
}
extension Building {
    // A method for printing the sales summary of the building,
    // describing what it is along with its other properties.
    func printSalesSummary() {
        print("# Sales Summary \(Date().formatted()) #") // get the current date
        print("Building: \(name)\nBuilding Type: \(type)\nNumber of rooms: \(rooms)\nName of agent: \(agent)\nCost of building: \(cost.formatted(.currency(code: "USD")))")
        print("#####")
    }
}
struct House: Building {
    var rooms: Int
    var newRooms: Int { //adding new rooms
        get {
            return rooms
        }
        set {
            rooms = newRooms+newValue
        }
    }
    var cost: Int
    let agent: String
    let name: String
    let type: BuildingType
    // method to add new rooms & print a report
    mutating func modifyBuilding(newRoomsToAdd: Int) {
        print("# Major Modificates Done #")
        print("\(newRoomsToAdd) rooms are being added, to the existing \(rooms).")
        self.newRooms=newRoomsToAdd
        print("Work done. Total number of rooms now: \(rooms).")
        print("#####")
    }
}

struct Office: Building {
    var rooms: Int
    var cost: Int
    let agent: String
    let name: String
    let type: BuildingType
}

var house = House(rooms: 3, cost: 500_000, agent: "Smith & Sons Co", name: "12 Main Street", type: BuildingType.house)
house.modifyBuilding(newRoomsToAdd: 5)
print()
house.printSalesSummary()

   

Hacking with Swift is sponsored by Stream

SPONSORED Build Chat messaging quickly with Stream Chat. The Stream iOS Chat SDK is highly flexible, customizable, and crazy optimized for performance. Take advantage of this top-notch developer experience, get started for free today!

Click here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.