1

Is it possible to add subclassed objects to a static array inside the parent class? I would like to run a function on all instances created. Another SO question describes being able to loop over an array to call a function on each instance and I think this is the end result I would like as well but my problem is even getting the instances into a static array that keeps track of all instances.

Of course my code is more modular but here is a simplified view of the code and hierarchy:

class Jungle {

    static var jungle: [Animals] = []

}

class Tigers: Animals {
    static var tigerPopulation: Int = 0

    override init(name:String){
        super.init(name: name)
        Tigers.tigerPopulation += 1
    }

    deinit {
        Tigers.tigerPopulation -= 1
    }

}

class Monkeys: Animals {
    static var monkeysPopulation: Int = 0


    override init(name: String){
        super.init(name: name)
        Monkeys.monkeysPopulation += 1
    }
    deinit {
        Monkeys.monkeysPopulation -= 1

    }

}

class Snakes: Animals {
    static var snakePopulation: Int = 0

    override init(name: String){
        super.init(name: name)
        Snakes.snakePopulation += 1
    }
    deinit {
        Snakes.snakePopulation -= 1
    }
}

I get the feeling that I should have created the Jungle class first so they all would subclass from Jungle I guess but I'm still stumped on how I would get the instances into an array.

6
  • 1
    just Jungle.jungle.append wont work? Commented Jan 6, 2017 at 4:17
  • @Tj3n if I put that inside of each species init function, how would I say "append this instance that was just created"? I wrote that out but couldn't get it right as to what to append while inside the init function of each species. I may be thinking incorrectly all together. Commented Jan 6, 2017 at 4:20
  • 2
    Your code makes no sense - there is no Animals class, so what are all these other classes deriving from? Commented Jan 6, 2017 at 4:21
  • 1
    Also please at least give some example of what you are hoping to accomplish. Your question is completely unclear at the moment... Commented Jan 6, 2017 at 4:22
  • @matt Right now each species (tiger, monkey, snakes) is subclassed from Animal. The end goal is to create an array that holds all Animal instances thats created at initialization. Is that possible? Commented Jan 6, 2017 at 4:23

1 Answer 1

4

Instead of trying to trigger some behavior to increase the monkey count, tiger count etc from within an initializer, it will be easer to just add everything to an animals array, and then use the animals array to figure out how many Tigers/Snakes/Monkeys there are.

Basing the count off that single array is going to be easier in the long term than having a bunch of different variables, and making sure they're in sync (e.g. by decreasing during deinit).

Here's a minor reshuffle of your jungle, animal, and animal subclasses:

class Jungle {

    var animals: [Animal] = []

    func addAnimal(animal: Animal) {
        animals.append(animal)
    }

    // this is a computed property, everytime you access it
    // via jungle.tigerPopulation, the code inside this statement
    // executes, and you get the value that is returned
    var tigerPopulation: Int {

        // tigers is a new array containing only tigers
        let tigers = animals.filter{ animal in
            return animal is Tiger
        }

        // return the number of items in the tigers array
        return tigers.count
    }
}

class Animal {
    let name: String
    init(name: String) {
        self.name = name
    }

    func sayHello() {
        print("I'm an animal")
    }
}

class Tiger: Animal {
    // tiger specific stuff
    override func sayHello() {
        print("I'm a tiger called", name)
    }
}

class Monkey: Animal {
    // monkey specific stuff
}

class Snake: Animal {
    // snake specific stuff
    override func sayHello() {
        print("I'm a snake called", name)
    }
}

Something to point out is that because each of the animal subclasses are currently doing the same thing (assigning the name) you don't need to override the initializer in the subclasses - that's the value of class inheritance!

You can override the subclasses sometimes in the future if an animal has to do something that's different from other animals.

The most interesting thing that's happening here is the computed property that calculates the tiger population by filtering the tigers in the animals array, and returning the count, this way you're not manually +/- 1 the population count, but just calculating it whenever you ask for it.

Then you'd use your jungle object something like this:

let jungle = Jungle()
// jungle.animals -> []
// jungle.animals.count -> 0
// jungle.tigerPopulation -> 0

jungle.addAnimal(animal: Tiger(name: "Tony"))
// jungle.animals -> [Tiger()]
// jungle.animals.count -> 1
// jungle.tigerPopulation -> 1

jungle.addAnimal(animal: Snake(name: "Susan"))
// jungle.animals -> [Tiger(), Snake()]
// jungle.animals.count -> 2
// jungle.tigerPopulation -> 1


for animal in jungle.animals {
    animal.sayHello()
}
// prints ->
// I'm a tiger called Tony
// I'm a snake called Susan
Sign up to request clarification or add additional context in comments.

4 Comments

this really helps in getting how it could have been accomplished better and I'm appreciative. My end goal was to simply have an array of all the animals and then loop through it to invoke a function that they all share but in their own way or implementation. Do you think I took the long route this way in order to invoke a function across all instances?
you could have animals add themselves to the jungle.animals array when they are created, but it's going to end up with some confusing and hard to maintain code. You Animal/Tiger/Snake objects should only be worried about managing themselves as an object, with the next level up (the jungle) having responsibility for adding/removing them.
I also updated the answer to include an example of a sayHello() method and how you can look over the animals array to call it for each animal, and how that creates a slightly different message for each animal. You might want to check out this post for some ideas on object oriented patterns: raywenderlich.com/81952/…
good call, thats the tutorial I started from and then got so excited and just started doing my own thing based on what I learned half way through thinking to myself I'm doing something whimsical. Your logic is so much easier to read compared to what I had. Much appreciative

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.