WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Checkpoint 7: Cats and Dogs

Forums > 100 Days of SwiftUI

For Checkpoint 7, Paul asks us to demonstrate an understanding of class inheritence. Here's my crack at it. Make sure you try it on your own before critiquing my code! Please provide improvements.

class Animal {
    let legs: Int  // typically attached to feet
    init (legs : Int) { self.legs = max(legs, 0)  } // cannot be negative
}

class Dog: Animal {
    init() { super.init( legs: 4 ) }       // dogs are quadrupeds.
    public func speak() { print("bark") }  // standard implementation
}

class Cat: Animal {
    let isTame: Bool
    init ( isTame isTameFromInit: Bool) {
        isTame = isTameFromInit
        super.init(legs: 4) // cats are quadrupeds.
    }
    public func speak() { print("meow?") }
}

class Corgi:  Dog { override func speak() { print ("YAP YAP YAP!")     }}
class Poodle: Dog { override func speak() { print ("WOOF!")            }}

class Persian: Cat {
    init() { super.init(isTame: true)}
    override func speak() { print("Yowwwww Yowwwwww") }}
class Lion:    Cat {
    init() { super.init(isTame: false)}
    override func speak() { print("Roooooooar")       }}

// ====================================
// Test cases to try in Playground   
let larry = Corgi()    // create an instance of the Corgi class
let moe   = Poodle()
let curly = Persian()
let shemp = Lion()

print ("Larry is a dog with \(larry.legs) legs. Larry says ")
larry.speak() ; print("\n")
print ("Moe is a dog with \(moe.legs) legs. Moe says ")
moe.speak() ; print("\n")
print ("Curly is a " + (curly.isTame ? "tame " : "wild ") + "cat with \(curly.legs) legs. Curly says ")
curly.speak() ; print ("\n")
print ("Shemp is a " + (shemp.isTame ? "tame " : "wild ") + "cat with \(shemp.legs) legs. Shemp says")
shemp.speak() ; print("\n")

4      

Really great work and I have no complains! I just want to share my solution as well. It´s simpler than yours and I hope it´s not false.

class Animal {
    let legs: Int

    init(legs: Int) {
        self.legs = legs
    }
}

    class Dog: Animal {
        func speak() {
            print("Bark, Bark with \(legs) legs")
        }
//        init() {
//            super.init(legs: 4)
//        }
    }

        class Corgi: Dog {
            override func speak() {
                print("Wau Wau I am a Corgi and I have \(legs) legs")
            }
        }
        class Poodle: Dog {
            override func speak() {
                print("Wuff Wuff I am a Poodle and I have \(legs) legs")
            }
        }

    class Cat: Animal {
        var isTame: Bool
        func speak() {
            print("Mew Mew")
        }

        init(legs: Int, isTame: Bool) {
            self.isTame = isTame
            super.init(legs: legs) //or (legs: 4)
        }

    }

        class Persian: Cat {
            override func speak() {
                print("Miau Miau Cat \(legs) legs and isTame = \(isTame)")
            }
        }

        class Lion: Cat {
            override func speak() {
                print("Miz Miz I am a Cat with \(legs) legs and isTame? \(isTame)")
            }
        }

let random = Persian(legs: 8, isTame: true)
random.speak()
let random2 = Lion(legs: 4, isTame: false)
random2.speak()

2      

I thought it would be fun to try putting a variable called voice and a single Speak() method inside the Cat and Dog subclasses and then use super.init to change the voice:

class Animal { let legs = 4 }

class Dog: Animal {
    var voice: String

    init(voice: String = "Woof") { self.voice = voice }

    func speak() { print("\(voice)!") }
}

class Cat: Animal {
    var voice: String
    var isTame: Bool

    init(voice: String = "Meow", isTame: Bool) {
        self.voice = voice
        self.isTame = isTame
    }

    func speak() { print("\(voice)!") }
}

class Persian: Cat {
    init() { super.init(voice: "Yowl", isTame: true) }
}
class Lion: Cat {
    init() { super.init(voice: "Roar", isTame: false) }
}
class Corgi: Dog {
    init() { super.init(voice: "Ruff") }
}
class Poodle: Dog {
    init() { super.init(voice: "Yip yip") }
}

2      

Hacking with Swift is sponsored by Fernando Olivares

SPONSORED Fernando's book will guide you in fixing bugs in three real, open-source, downloadable apps from the App Store. Learn applied programming fundamentals by refactoring real code from published apps. Hacking with Swift readers get a $10 discount!

Read the book

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

not sure if this is the right way, new to dev work

class Animal {
    let legs = 4
    func speak(spk: String){
        print("this animal will speak with sound as \(spk)")
    }
}

let Dog = Animal()
class Cat: Animal {
    let isTame: Bool
    init(isTame: Bool){
        self.isTame = isTame
    }
}

let Poodle = Dog
let corgi = Dog
let lion = Cat.init(isTame: true)
let persian = Cat.init(isTame: false)

print(Poodle.speak(spk: "bow and have \(Poodle.legs) legs"))
print(corgi.speak(spk: "Roar and have \(corgi.legs) legs"))
print(lion.speak(spk: "meow and have \(lion.legs) legs"))
print(persian.speak(spk: "meoooooow meow and have \(persian.legs) legs"))

1      

Here's my solution. Xcode isn't mad about it, and I had fun. Maybe it could've been simpler, but it works and I think it checks all the boxes.

class Animal {
    var hasLegs: Int
    init(hasLegs: Int) {
        self.hasLegs = hasLegs
    }
    func speak() {
        hasLegs = 4
        print("Animals have \(hasLegs) legs and make their own sounds.")
    }
}

class Dog: Animal {
    init() {
        super.init(hasLegs: 4)
    }
    override func speak() {
        hasLegs = 4
        print("Dogs have \(hasLegs) legs and say Bork.")
    }
}

class Corgi: Dog {
    override func speak() {
        hasLegs = 4
        print("Corgis have \(hasLegs) legs and say BORK!")
    }
}

class Poodle: Dog {
    override func speak() {
        hasLegs = 4
        print("Poodles have \(hasLegs) legs and say BORK BORK!")
    }
}

class Cat: Animal {
    var isTame: Bool
    init(isTame: Bool) {
        self.isTame = isTame
        super.init(hasLegs: 4)
    }
    override func speak() {
        hasLegs = 4
        print("Cats have \(hasLegs) legs, are generally tame, and say meow.")
    }
}

class Persian: Cat {
    init() {
        super.init(isTame: true)
    }
    override func speak() {
        isTame == true
        let behavior: String
        hasLegs = 4

        if isTame == true {
            behavior = "are tame"
        } else {
            behavior = "are wild"
        }

        print("Persians \(behavior), have \(hasLegs) legs, and say MeeOW.")
    }
}

class Lion: Cat {
    init() {
        super.init(isTame: false)
    }
    override func speak() {
        isTame == false
        let behavior: String
        hasLegs = 4

        if isTame == true {
            behavior = "are tame"
        } else {
            behavior = "are wild"
        }

        print("Lions \(behavior), have \(hasLegs) legs, and say RAWR.")
    }
}

let animal = Animal(hasLegs: 4)
animal.speak()

let animal1 = Dog()
animal1.speak()

let animal2 = Cat(isTame: true)
animal2.speak()

let animal3 = Corgi()
animal3.speak()

let animal4 = Poodle()
animal4.speak()

let animal5 = Persian()
animal5.speak()

let animal6 = Lion()
animal6.speak()

1      

Nice!

This is allowable, but I wonder why you did this.

    override func speak() {
        hasLegs = 4  // <==== ???
        print("Dogs have \(hasLegs) legs and say Bork.")
    }

When you initialize a dog, or a cat, you give both 4 legs in your initializer.
Your speak() function can use the class' hasLegs variable. You do NOT have to assign hasLegs a value in the speak() function.

Additionally, one might argue that asking a dog or a cat object to speak() is NOT the place where you should be assigning their number of legs! Assigning leg count probably should be in its own function, but probably NOT in the speak() function.

Finally, think about your variable hasLegs. This kinda, sorta sounds like a question. Does a snake hasLegs? (no) Does a fish hasLegs? (again, no) Does a dog hasLegs? (yes!)

In @twostraw's lessons you'll start to see how he names variables. hasLegs probably should be a boolean (true or false). Consider what might be a better name for your variable. What does it hold? For each animal it holds the leg quanity, or count.

Consider renaming your variable from hasLegs to legCount, or something similar.

Keep going! Let us know when you have additional questions, or need help.

   

Thanks for the feedback! This is my first true attempt at learning a programming language. I'll revisit this checkpoint and circle back. :)

Update! I think part of my issue was that I couldn't let go of putting a leg count in there and not using it for something. speak() now takes care of just itself, checkLegs() will look back at the data in class Animal, and checkTame() will look at behavior for cats.

class Animal {
    let legCount = 4

    func speak() {
        print("Animals make their own sounds.")
    }

    func checkLegs() {
        print("Lots of animals have \(legCount) legs.")
    }
}

class Dog: Animal {
    override func speak() {
        print("Bork")
    }

    override func checkLegs() {
        print("Dogs have \(legCount) legs.")
    }
}

class Corgi: Dog {
    override func speak() {
        print("BORK")
    }

    override func checkLegs() {
        print("Corgis have \(legCount) short legs.")
    }
}

class Poodle: Dog {
    override func speak() {
        print("BORK BORK")
    }

    override func checkLegs() {
        print("Poodles have \(legCount) legs, too.")
    }
}

class Cat: Animal {
    var isTame: Bool
    init(isTame: Bool) {
        self.isTame = isTame
    }
    override func speak() {
        print("Meow")
    }
}

class Persian: Cat {
    init() {
        super.init(isTame: true)
    }
    override func speak() {
        print("MeeOWW")
    }

    func checkTame() {
        let behavior: String
        if isTame == true {
            behavior = "are tame"
        } else {
            behavior = "are wild"
        }
        print("Persians \(behavior).")
    }
}

class Lion: Cat {
    init() {
        super.init(isTame: false)
    }
    override func speak() {
        print("RAWR")
    }

    func checkTame() {
        let behavior: String
        if isTame == true {
            behavior = "are tame"
        } else {
            behavior = "are wild"
        }
        print("Lions \(behavior).")
    }
}

   

Heey nice code, I've been checking every Checkpoint post you made, is been very helpful. This is by far my favorite checkpoint, so I would like to share my solution for the first time:

class Animal {
    let legs = 4
}
class Dog: Animal {
    func speak () {
        print ("AUU AUUU AUU")
    }
}
class Corgi: Dog {
   override func speak () {
        print ("This Corgi is soo short 🥺")
    }
}
class Poodle: Dog {
    override func speak () {
         print ("This Poodle is pissing in the pool 😩")
     }
}
class Cat: Animal {
    var isTame: Bool
    func speak () {
        print ("MEOOOWW")
    }
    init(isTame: Bool) {
        self.isTame = isTame
    }
}
class Persian: Cat {
    override func speak () { if isTame {
        print ("Good cat! ☺️")}
        else {
            print ("He just bited me! 😠")
        }
     }
}
class Lion: Cat {
override func speak () { if isTame {
    print ("Good lion! ☺️")}
    else {
        print ("RUUUUUUUUUNN 😱")
    }
 }
}
let leão = Lion (isTame: true)
leão.speak()

   

Hi all, just finished up Checkpoint 7, and I'm not super happy with it, but it works.

My biggest issue is that I didn't see the need to incorporate a method override, and my initial Animal class is empty 😬

Again, all feedback is very much appreciated.

class Animal {

}

class Dog: Animal {
    var myBark = "Woof!" //default bark if none supplied
    var numLegs = 4
    init(numLegs: Int){
         self.numLegs = numLegs
    }
    func speak(dogName: String, myBark: String){
        print("\(dogName) says \"\(myBark)\"")
    }
}

class Corgi: Dog {
    var name = "Random Corgi" //default name if none supplied
    var corgiBark = "Bow Wow!" //default bark if none supplied
}

class Poodle: Dog {
    var name = "Random Poodle" //default name if none supplied
    var poodleBark = "Good Day, sir." //default bark if none supplied
}

class Cat: Animal {
    var isTame = false
    var numLegs = 4
    init(isTame: Bool, numLegs: Int){
        self.isTame = isTame
        self.numLegs = numLegs
    }
    func speak(catName: String, myMeow: String){
        print("\(catName) says \"\(myMeow)\"")
    }
}

class Persian: Cat {
    var name = "Random Persian" //default name if none supplied
    var meow = "Oh, meow what's the matter?" //default meow if none supplied
}

class Lion: Cat {
    var name = "Random Lion" //default name if none supplied
    var meow = "Roar, I guess" //default meow if none supplied
}

let princess = Corgi(numLegs: 4)
princess.name = "Princess"
princess.speak(dogName: princess.name, myBark: princess.corgiBark)

let mrSnobby = Poodle(numLegs: 3)
mrSnobby.name = "Mr Snobby"
mrSnobby.speak(dogName: mrSnobby.name, myBark: mrSnobby.poodleBark)

let giles = Persian(isTame: true, numLegs: 4)
giles.name = "Giles Jr the 3rd"
giles.speak(catName: giles.name, myMeow: giles.meow)

let kimba = Lion(isTame: false, numLegs: 4)
kimba.name = "Kimba"
kimba.speak(catName: kimba.name, myMeow: "I used to be on the telly, you know...")

   

Ben seeks feedback on Checkpoint 7:

I didn't see the need to incorporate a method override, and my initial Animal class is empty.
Again, all feedback is very much appreciated.

You're in the early stages of this SwiftUI course. While your code compiles and works, you may have missed the point of this lesson. Namely, class inheritence. If you have previous experience with object oriented languages (Java, C++) this might be a lesson you already know.

The object of this lesson is to learn the syntax for gathering similar object properties into a parent object. This lets subclasses inherit the parent's properties and functions while only sightly modifying the child object.

What do cats and dogs have in common?
The common elements probably belong in the parent class: Animal.

// Define the PARENT class
class Animal {
    // Add common elements to a parent class
    var animalVoice  = "Bark, Meow, or Roar" // Depends on the subclass.
    var numberOfLegs = 4 // Or it could be two for a kangaroo?

    //  function common to most animals
    //  You may want to override this method if your animal (turtles?) don't speak.
    func speak() {
        print("This animal says \(animalVoice)")
    }
}

// Define a SUBCLASS that inherits properties and functions.
class Dog: Animal {
    var myBark  = "Woof!" // consider using the Animal class' animalVoice property.
    var numLegs = 4  // This is redundant. The parent class provides the capability to store leg count.
    init(numLegs: Int){
         self.numLegs = numLegs
    }
    // This is REDUNDANT code. You have the same code in both the cat and dog classes. ☹️
    func speak(dogName: String, myBark: String){
        print("\(dogName) says \"\(myBark)\"")
    }
}

class Cat: Animal {
    // ---- snip ---
    // This is REDUNDANT. This is a candidate for the parent class. 🤔
    func speak(catName: String, myMeow: String){
        print("\(catName) says \"\(myMeow)\"")
    }
}

Also note most dogs have 4 legs. So consider changing this Dog initializer. What is NOT common among most dogs? Right, most dogs have different names. Consider a Dog initializer that accepts the dog's name.

let princess = Corgi(numLegs: 4)  // Probably not useful in the long term.
princess.name = "Princess"
princess.speak(dogName: princess.name, myBark: princess.corgiBark)

// Instead consider:
let princess = Corgi(name: "Anne, Princess Royale") // Assign name when created. By default, Anne has 4 legs.
// Also, a Dog object has a name. So no need to pass to the speak function.
princess.speak()  // Use the default animal voice.
// or
princess.voice = "Spot of tea, if you bark." // Add a new voice for this instance.
princess.speak() // Use the updated animal voice.

   

FWIW, here's my take on it (notes below the code):

// Checkpoint 7

class Animal {
    let legs: Int

    init(legs: Int) {
        self.legs = legs
    }

    func speak() { }
}

class Dog: Animal {
    init() {
        super.init(legs: 4)
    }
}

class Cat: Animal {
    var isTame: Bool

    init(isTame: Bool) {
        self.isTame = isTame
        super.init(legs: 4)
    }
}

class Bird: Animal {
    var canFly: Bool

    init(canFly: Bool) {
        self.canFly = canFly
        super.init(legs: 2)
    }
}

final class Corgi: Dog {
    override func speak() {
        print("Yip Yip Yip")
    }
}

final class Poodle: Dog {
    override func speak() {
        print("Ooo la barking la")
    }
}

final class Persian: Cat {
    init() {
        super.init(isTame: true)
    }

    override func speak() {
        print("Meow")
    }
}

final class Lion: Cat {
    init() {
        super.init(isTame: false)
    }

    override func speak() {
        print("ROAR!")
    }
}

final class Crow: Bird {
    init() {
        super.init(canFly: true)
    }

    override func speak() {
        print("Caw caw")
    }
}

final class Ostrich: Bird {
    init() {
        super.init(canFly: false)
    }
}

let fido = Corgi()
let spot = Poodle()
let princess = Persian()
let leo = Lion()
let carlos = Crow()
let oscar = Ostrich()

fido.speak()
spot.speak()
princess.speak()
leo.speak()
carlos.speak()
oscar.speak()

Notes:

  1. Since almost all animals can speak, I moved the speak() function up to the Animal class.
  2. I added super.init() calls in the Animal direct subclasses to set the number of legs. (P.S. below)
  3. I added an additional Bird class just to fiddle with different number of legs.
  4. I assumed Ostriches can't speak, and appropriately, calling Ostrich.speak() does nothing, simply because I did not override the speak() method for this class.

P.S.: In his solution, Paul did not show the Dog class (or its subclasses) calling super.init(), which I don't understand. How does the legs property get set for dogs then?

   

Here's my take, I tried to include the name of the instance in the speak method but encountered a suffix of each name "lldb_expr_266." Removed the suffix and then the program worked as expected!

Originally had two methods (speak() and tameStatus()) but attempted to combine them.

Any feedback or tips are appreciated!!

//Master Parent Class
class Animal {
    //legs property: will be inherited
    let legs: Int
    let sound: String

    //initializer to set legs value that will be inherited
    init(legs: Int, sound: String){
        self.legs = legs
        self.sound = sound
    }
    //method to print animal name, list sound and number of legs
    func speak(_ remove: String = "__lldb_expr_266." ) {
        //self gets the name of a a particular instance but adds the above suffix
        var animalName = "\(self)"
        for _ in 1...16{
        animalName.remove(at: animalName.startIndex)
        }
        print("I am a \(animalName) and I \(sound), I have \(legs) legs")
    }
}

//child class of Animal: dog
class Dog: Animal {
}

//child class of Animal: cat
class Cat: Animal {
    let isTame: Bool

    init(legs: Int, isTame: Bool, sound: String){
        self.isTame = isTame
        super.init(legs: legs, sound: sound)
    }
    //same as parent function but adds tame status
    override func speak(_ remove: String = "__lldb_expr_266." ){
        var animalName = "\(self)"
        for _ in 1...16{
        animalName.remove(at: animalName.startIndex)
        }
        if isTame == true{
               print("I am a \(animalName) and I \(sound), I have \(legs) legs, I'm tame")
           } else{
           print("I am a \(animalName) and I \(sound), I have \(legs) legs, I'm wild")
           }
       }
}

//child classes of Dogs
class Corgi: Dog {
}
class Poodle: Dog {
}
//child classes of Cats
class Lion: Cat {
}
class Persian: Cat {
}
//Initialization
let genericDog = Dog(legs: 4, sound: "bark")
let genericCat = Cat(legs: 4, isTame: true, sound: "meow")
let poodle = Poodle(legs: 4, sound: "bark")
let corgi = Corgi(legs: 4, sound: "bark")
let lion = Lion(legs: 4, isTame: false, sound: "roar")
let persian = Persian(legs: 4, isTame: true, sound: "bark")

//calling speak
genericDog.speak()
genericCat.speak()
poodle.speak()
corgi.speak()
lion.speak()
persian.speak()

Output:

I am a Dog and I bark, I have 4 legs
I am a Cat and I meow, I have 4 legs, I'm tame
I am a Poodle and I bark, I have 4 legs
I am a Corgi and I bark, I have 4 legs
I am a Lion and I roar, I have 4 legs, I'm wild
I am a Persian and I bark, I have 4 legs, I'm tame

   

Ethan asks for feedback on this Day 12 checkpoint:

Any feedback or tips are appreciated!! I appreciate your feedback and tips!

Classes and Subclasses

As @twoStraws might say, "these are early days." True, you're not very far along with the lessons. So good job throwing code and getting some decent output. But, I think you may have missed the point of classes and subclasses. Let's review.

A parent class might hold properties that are common among all its children classes. This allows you to create child classes that have all the properties and methods of its parent, but with perhaps slightly more data properties, or a unique implementation of a method. This allows you to focus just on the differences between a parent and a child class.

Yet, your Dog, Corgi, and Poodle classes don't do this. You create child classes, but you do not add additional properties, nor do you modify any methods. In short, your Dog, Corgi, Poodle, and Animal classes are all the same. While they all share Animal characteristics, each child class should have slightly different properties, or methods.

// Your Dog class is a child class of Animal
class Dog: Animal {
}

// Corgi and Poodle are child classes of Dog
class Corgi: Dog {
}
class Poodle: Dog {
}

What you might consider is: What makes a Dog different from a generic Animal?
For example, someone might say a dog's default speak method is "Bark". This is what makes it different!
Also, you might consider, by default, a Dog pretty much has four legs.

So when you define a Dog class, consider adding these defaults. In contrast, the Cat class will have a different default speak method, but will also have 4 legs by default.

Then, when you futher refine your animals with a Corgi, or Poodle class, what might make these child classes different from a Dog class? For starters, both corgis and poodles will have four legs. But they already inherit this benefit from the Dog class. About the only thing you need to change is how they bark. One might "Yap" whilst the other "Borks".

Likewise a Lion is a Cat, but most always is not tame. Add that to the Lion subclass' default definition.

I recommend you redo this assignment. Focus on putting properties and functions in the proper level of your animal hierarchy. This is a thinking assignment. How do you classify the parts of objects?

Checking if a variable is true

As you code more, you'll see that code like this is redundant. Keep your logic simple. Let it read like a question.

// Your code:
    // Awkward!
    if isTame == true {  // <--- if this animal's isTame variable is equal to true.
        // do some stuff here...
    }

// Instead, let the if statement read like a simple question.
    if isTame { // <-- If this animal is tame   (nice!)
        // do some stuff here...
    }

Keep coding!

   

@Ethanxxxv, this function:

    //method to print animal name, list sound and number of legs
    func speak(_ remove: String = "__lldb_expr_266." ) {
        //self gets the name of a a particular instance but adds the above suffix
        var animalName = "\(self)"
        for _ in 1...16{
        animalName.remove(at: animalName.startIndex)
        }
        print("I am a \(animalName) and I \(sound), I have \(legs) legs")
    }

(and its override in the Cat class)

is very very fragile. You assume the type will always be preceded by something like __lldb_expr_266. and so chop off the first 16 characters in the String return by "\(self)" but this is not the case. For instance, when I run your code in a playground on my machine, this is the output:

I am a g and I bark, I have 4 legs
I am a t and I meow, I have 4 legs, I'm tame
I am a odle and I bark, I have 4 legs
I am a rgi and I bark, I have 4 legs
I am a on and I roar, I have 4 legs, I'm wild
I am a rsian and I bark, I have 4 legs, I'm tame

Because the __lldb_expr_#. part changes every time the code compiles. In my case, we're looking at __lldb_expr_7. the first time I ran it, and __lldb_expr_9. the second time.

Also, you don't need an if {} else {} clause in Cat.speak() if you use the ternary operator (Day 5). But that's really more of a stylistic thing to avoid duplicating the String being printed when the two options only vary by one word.

Better to do this:

class Animal {
    //...
    //method to print animal name, list sound and number of legs
    func speak() {
        print("I am a \(type(of: self)) and I \(sound), I have \(legs) legs")
    }
}

class Cat: Animal {
    //...
    //same as parent function but adds tame status
    override func speak(){
        print("I am a \(type(of: self)) and I \(sound), I have \(legs) legs, I'm \(isTame ? "tame" : "wild")")
    }
}

Using the built-in type(of:) function (I'm not sure when that's introduced during the 100 Days) to get the type name, I see this output:

I am a Dog and I bark, I have 4 legs
I am a Cat and I meow, I have 4 legs, I'm tame
I am a Poodle and I bark, I have 4 legs
I am a Corgi and I bark, I have 4 legs
I am a Lion and I roar, I have 4 legs, I'm wild
I am a Persian and I bark, I have 4 legs, I'm tame

   

Thank you @roosterboy and @Obelix .

Everytime I think I understand something I find out there's more too it but that's learning!

I appreciate your feedback and tips!!

Here is my updated code:

//Master Parent Class
class Animal {
    var legs: Int

    init(legs: Int = 4){
        self.legs = 4
    }

    func speak(){
        print("I am a \(type(of: self)), I have \(legs) legs")
    }
}

//child class of Animal: dog
class Dog: Animal {
    var sound:  String

    init(legs: Int = 4, sound: String = "bark"){
        self.sound = sound
        super.init(legs: legs)

    }
   override func speak(){
        print("I am a \(type(of: self)), I have \(legs) legs and I \(sound)")

    }
}

//child class of Animal: cat
class Cat: Animal {
    var sound:  String
    var tame: Bool

    init(legs: Int = 4, sound: String = "meow", tame: Bool = true){
        self.sound = sound
        self.tame = tame
        super.init(legs: legs)
    }

       override func speak(){
             print("I am a \(type(of: self)), I have \(legs) legs and I \(sound), my tame status is \(tame)")

    }
}

//child classes of Dogs
class Corgi: Dog {
    override  init(legs: Int = 4, sound: String = "Corgi bark"){
        super.init(legs: legs)
        self.sound = sound
    }
}

class Poodle: Dog {
    override  init(legs: Int = 4, sound: String = "Poodle bark"){
        super.init(legs: legs)
        self.sound = sound
    }
}

//child classes of Cats
class Lion: Cat {

  override  init(legs: Int = 4, sound: String = "Roar", tame: Bool){
      super.init(legs: legs)
      self.sound = sound
      self.tame = tame

    }
}
class Persian: Cat {
    override  init(legs: Int = 4, sound: String = "Persian Meow", tame: Bool = true){
        super.init(legs: legs)
        self.sound = sound
        self.tame = tame
      }
}

//Initialization
let genericAnimal = Animal()
let genericCat = Cat()
let persianCat = Persian()
let lionCat = Lion(sound: "override roar", tame: false)
let genericDog = Dog()
let corgiDog = Dog()
let poodleDog = Dog(legs: 6, sound: "mutant poodle bark")

genericAnimal.speak()
genericCat.speak()
persianCat.speak()
lionCat.speak()
genericDog.speak()
poodleDog.speak()

   

I tried to keep it simple. Thoughts, comments.

import Cocoa

class Animal {
    let legs: Int

    init(legs: Int) {
        self.legs = legs
    }
    func speak() {
        print("undetermined")
    }
}

class Dog: Animal {
    init() {
        super.init(legs: 4)
    }
}

class Cat: Animal {
    let isTame: Bool

    init(isTame: Bool) {
        self.isTame = isTame
        super.init(legs: 4)
    }
}

final class Corgi: Dog {
    override func speak() {
        print("Yap, yap, yip!")
    }
}

final class Poodle: Dog {
    override func speak() {
        print("Woof, woof, woof!!")
    }
}

final class Persian: Cat {
    init() {
        super.init(isTame: true)
    }
    override func speak() {
        print("Meow, meow, meow!")
    }
}

final class Lion: Cat {
    init() {
        super.init(isTame: false)
    }
    override func speak() {
        print("ROOAAAARRR!!")
    }
}

   

I love seeing everybody's implementations. It's inspiring and I'm learning a lot. Here is what I came up with initially, but I will take the time to look through all the different posts and see how I can spruce up my own code. Keep up the good work everybody!

class Animal {
    var legs: Int

    init(legs: Int) {
        self.legs = legs
    }
}

class Dog: Animal {
    func speak() {
        print("Woof!")
    }
}

class Cat: Animal {
    var isTame: Bool

    init(isTame: Bool, legs: Int) {
        self.isTame = isTame
        super.init(legs: legs)
    }

    func speak() {
        print("Meow!")
    }
}

class Corgi: Dog {
    override func speak() {
        print("Corgi bark!")
    }
}

class Poodle: Dog {
    override func speak() {
        print("Poodle bark!")
    }
}

class Persian: Cat {
    override func speak() {
        print("Persian meow!")
    }
}

class Lion: Cat {
    override func speak() {
        print("Lion ROAR!")
    }
}

var corgi = Corgi(legs: 4)
corgi.speak()

var poodle = Poodle(legs: 4)
poodle.speak()

var persian = Persian(isTame: true, legs: 4)
persian.speak()
print("Persians are tame", persian.isTame)

var lion = Lion(isTame: false, legs: 4)
lion.speak()
print("Lions are tame", lion.isTame)

Output

Corgi bark!
Poodle bark!
Persian meow!
Persians are tame true
Lion ROAR!
Lions are tame false

   

Hacking with Swift is sponsored by Fernando Olivares

SPONSORED Fernando's book will guide you in fixing bugs in three real, open-source, downloadable apps from the App Store. Learn applied programming fundamentals by refactoring real code from published apps. Hacking with Swift readers get a $10 discount!

Read the book

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.