Object-Oriented Programming: Beyond the Basics

Oct 17 2023 · Swift 5.9, iOS 17, Xcode 15

Lesson 02: Polishing Object-Oriented Programming Concepts

Demo 1

Episode complete

Play next episode

Next
Transcript

In this demo, your going to write some logic to determine whether a contact is a person or a company. The first thing to do is introduce the ability to mark a contact as a company. Open the starter Playground. It’s been refactored into separate files. Expand the navigator by clicking the Hide/Show navigator button. Expand the Sources folder, then open the ContactCard.swift file. Add this new field to the ContactCard definition:

public class ContactCard {
  let contactID: UUID
  var firstName: String
  var lastName: String
  var phoneNumber: String
  var relatedContacts: [UUID]
  public var isCompany: Bool // new code
  ...

This simply determines whether the contact is a company. Update the constructor to set the new property:

public init(firstName: String, lastName: String, phoneNumber: String) {
  self.firstName = firstName
  self.lastName = lastName
  self.phoneNumber = phoneNumber
  contactID = UUID()
  relatedContacts = []
  isCompany = false // new code
}

Return to the main playground file and create these two new companies:

let kodeco = ContactCard(firstName: "Kodeco", lastName: "", phoneNumber: "1111111111")
kodeco.isCompany = true

let razeware = ContactCard(firstName: "Razeware", lastName: "", phoneNumber: "1111111111")
razeware.isCompany = true

print(kodeco.contactInformation())
print(razeware.contactInformation())

Next, comment out the existing print statements to keep things clear

//print("Ehab contact contains Tim contact: \(containsTim)")
//print("Tim contact contains Ehab contact: \(containsEhab)")

Run the playground. You can see from the code that you defined a company contact exactly the same way as you define a person, except that you set isCompany to true right after the creation of the contact.

The next step is to create the relation between the new companies and the contacts you created from the previous lesson. Add the following right after the last code and before the print statements:

kodeco.addRelatedContact(razeware)
kodeco.addRelatedContact(ehabContact)

Print out Ehab’s contact information:

print(ehabContact.contactInformation())

Run the playground. Look at the number of connections. Both Kodeco and Ehab have two connections. This goes against the requirements! People are only allowed to have a two way relationship with other people but not companies. Yet Ehab has a connection to Tim, and Kodeco. Companies, on the other hand, can have a two way connection to other companies, but they keep a one way connection to people. This one way connection indicates a list of employees.

To fix this, go to the implementation of addRelatedContact(_:). Add a check for companies to skip the addition of the other direction relationship if the contact is a person:

public func addRelatedContact(_ contact: ContactCard) {
  relatedContacts.append(contact.contactID)

    if isCompany == true && contact.isCompany == true {
      print("Both this contact and the new contact are companies. Adding 2-way relationship")
      contact.relatedContacts.append(contactID)
    } else if isCompany == false && contact.isCompany == false {
      print("Both this contact and the new contact are people. Adding 2-way relationship")
      contact.relatedContacts.append(contactID)
    }
}

The updated method now properly meets the requirements, but you can make the code a little cleaner.

Notice that in the two conditions, it’s either both properties are true or both properties are false. So why not just check if the two properties are equal? Change the implementation of the function to the following:

public func addRelatedContact(_ contact: ContactCard) {
  relatedContacts.append(contact.contactID)

  if isCompany == contact.isCompany {
    print("Both this contact and the new contact are the same type. Adding 2-way relationship")
    contact.relatedContacts.append(contactID)
  }
}

Run the playground. The code now meets the requirements. And top of that, the code is much cleaner. Or is it?

See forum comments
Cinema mode Download course materials from Github
Previous: Instruction 1 Next: Instruction 2