Gold challenge for Ch. 16 -- a question


#1

On the Gold Challenged, I’m not getting it to work exactly like I want to.

Like someone else mentioned, I want to add a variable and method in Mayor to establish the anxiety level and to increment that value with the method. Using a setter was not an option because you can’t have an initial value with a getter/setter, so a method was the only way I saw to do this:

struct  Mayor {
    var name: String?
    var anxietyLevel = 0

    func sad() {
        if let thisMayor = name { 
            print("A special message from Mayor \(thisMayor): I am deeply saddened to hear about this latest tragedy.  I promise that my office is looking into the nature of this rash of violence.")
        }
    }
    mutating func anxious() {
            anxietyLevel += 1
//The next print statement is just a test to see if it is incrementing up properly.
            if let aMayor = name {
                 print("Mayor: \(aMayor), Anxiety Level: \(anxietyLevel).")
            }
        }
    }

My idea was to trigger the anxiety level change from the Zombie class (instructions spoke specifically of Zombie class), so I just added an extra line of code in Zombie to trigger the method in the Mayor structure. The one extra line is: " town?.mayor?.anxious()". I had a ton of difficulty trying to figure out how to reference the correct instance of the particular town’s mayor, but this appears to do it.

class Zombie: Monster { // "Zombie" inherits from "Monster" class
    var walksWithLimp = true
//    internal private(set) var isFallingApart = false // getter should be internal and setter is private
    private(set) var isFallingApart = false // access control defaults to internal
    override class var spookyNoise: String { //a computed type property for a zombie.
        return "Brains..."
    }
    
    final override func terrorizeTown() { // final indicates that subclasses can't override further.
        if let thisTown = town {
            if thisTown.population > 10 && isFallingApart != true {
        town?.changePopulation(by: -10) // optional chaining -- makes sure that it is safe to call a function on the "town" instance.
        super.terrorizeTown() // "super" accesses the superclasses' implementation of a method.
        town?.mayor?.anxious()
            } else {
                town?.population = 0 // optional chaining.
                print("They're all dead!") 
            }
        }
    }
}

If you have the Zombie terrorize the town, the anxiety level of the particular mayor in question does increment up, and the extra print line in the Mayor code shows the increment.

The problem is that if I try to check on the anxiety level from “main,” I cannot get the code to show me anything other than “0.” Here is the code I use in “main” to identify the town and mayor and then attempt to check on the the mayor’s anxiety level:

var myTown = Town()
var theMayor = Mayor()
theMayor.name = "Tom Brown"
myTown.mayor = theMayor
if let thisMayor = myTown.mayor?.name {
    print("The Mayor is \(thisMayor).")
}
let myTownSize = myTown.townSize

let fredTheZombie = Zombie()
fredTheZombie.town = myTown
var fredsName = "Fred the Zombie"
fredTheZombie.name = fredsName 
fredTheZombie.terrorizeTown()
fredTheZombie.terrorizeTown()
if let anxietyTest = myTown.mayor?.anxietyLevel, let boss = myTown.mayor?.name {
    print("The anxiety level of \(boss), is \(anxietyTest).")
}

No matter what I do, I cannot get the mayor’s anxiety level to show up by a call from “main.” It always shows “0”. The Mayor shows the correct name, but anxietyLevel is always zero. :frowning:


#2

As a followup, I’ve found that I can have the Zombie method call to a function in Main. Main then calls the method in Mayor to increment the anxiety level:

class Zombie: Monster { 
    var walksWithLimp = true
    private(set) var isFallingApart = false
    
    final override func terrorizeTown() { 
        if let thisTown = town {
            if thisTown.population > 10 && isFallingApart != true {
        town?.changePopulation(by: -10) 
        super.terrorizeTown() 
        //town?.mayor?.anxious()
        iMReallyAnxious() //the new function call in Main
            } else {
                town?.population = 0 
                print("They're all dead!") 
            }
        }
    }
}

The main bit is really simple:

func iMReallyAnxious() {
    myTown.mayor?.anxious()
}

The print line is just a double check to make sure it’s working.

The Mayor method is simple:

mutating func anxious() {
         self.anxietyLevel += 1
     if let aMayor = name {
          print("Mayor: \(aMayor), Anxiety Level: \(anxietyLevel).")
     }
 }