2017-01-06 2 views
-1

Можно ли добавлять объекты подкласса в статический массив внутри родительского класса? Я хотел бы запустить функцию во всех созданных экземплярах. Другой вопрос SO описывает возможность перебора массива для вызова функции для каждого экземпляра, и я думаю, что это конечный результат, который мне бы тоже хотелось, но моя проблема даже в том, что экземпляры попадают в статический массив, который отслеживает все экземпляры.Добавление объектов в статический массив в swift

Конечно мой код более модульным, но здесь это упрощенное представление кода и иерархии:

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 
    } 
} 

я чувствую, что я должен был создан класс джунглей первый, так что все они будут подклассы из джунглей Я предполагаю, но я все еще в тупике о том, как получить экземпляры в массив.

+1

просто 'Jungle.jungle.append' обыкновение работать? – Tj3n

+0

@ Tj3n, если я помещаю это внутри каждой функции init каждого вида, как бы я сказал «добавить этот экземпляр, который только что был создан»? Я написал это, но не мог понять, что добавить в функции init каждого вида. Возможно, я думаю неправильно. –

+2

Ваш код не имеет смысла - нет класса «Животные», поэтому из чего все эти другие классы? – matt

ответ

2

Вместо того чтобы пытаться вызвать какое-либо поведение, чтобы увеличить количество обезьян, счетчик тигра и т. Д. Из инициализатора, будет проще просто добавить все в массив животных, а затем использовать массив животных, чтобы выяснить, сколько тигров/Змеи/Обезьяны есть.

Основание подсчета этого одиночного массива будет проще в долгосрочной перспективе, чем наличие множества переменных, и убедитесь, что они синхронизированы (например, путем уменьшения во время deinit).

Вот небольшая рокировка ваших джунглей, животных, и подклассы животных:

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) 
    } 
} 

Что-то отметить, что, поскольку каждый из подклассов животных в настоящее время делают то же самое (присвоение имени) вы не Не нужно переопределять инициализатор в подклассах - это значение наследования класса!

Вы можете переопределять подклассы иногда в будущем, если животное должно делать что-то отличное от других животных.

Самое интересное, что здесь происходит, это computed property, который вычисляет популяцию тигра, фильтруя тигров в массиве животных и возвращая счет, таким образом, вы не вручную +/- 1, а подсчитываете количество людей вычисляя его всякий раз, когда вы просите об этом.

Тогда вы будете использовать ваши джунгли объект что-то вроде этого:

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 
+0

это действительно помогает в получении того, как это могло быть достигнуто лучше, и я благодарен. Моя конечная цель состояла в том, чтобы просто иметь массив всех животных, а затем прокручивать его, чтобы вызвать функцию, которую они все разделяют, но по-своему или по реализации. Как вы думаете, я сделал длинный маршрут таким образом, чтобы вызвать функцию во всех случаях? –

+1

Вы можете * добавить животных в джунгли.массив животных, когда они созданы, но в конечном итоге это приведет к некоторому запутанному и трудноподдерживающемуся коду. Объекты Animal/Tiger/Snake должны только беспокоиться о том, чтобы управлять собой как объектом, а следующий уровень (джунгли) несет ответственность за их добавление/удаление. – MathewS

+1

Я также обновил ответ, чтобы включить пример метода sayHello() и как вы можете просматривать массив животных, чтобы называть его для каждого животного, и как это создает немного другое сообщение для каждого животного. Возможно, вам захочется ознакомиться с этой записью для некоторых идей по объектно-ориентированным шаблонам: https://www.raywenderlich.com/81952/intro-object-oriented-design-swift-part-1 – MathewS

Смежные вопросы