Я не совсем уверен, есть ли конкретная причина, по которой функциональность в -setup
просто не может быть реорганизована в -initWithFrame:
, поэтому я собираюсь отказаться от этого ответа с просьбой увидеть более точную версиюваши методы, чтобы мы могли видеть, когда -setup
вызывается.
В том-то и дело, что в какой-то момент, где-то, вы должны помнить «выполнять действия в определенном порядке», если хотитеправильно инициализированный объект - особенно когда он включает иерархии классов.Как работает ваш текущий пример, все подклассы Metrics, а также их подклассы вызывают один и тот же, в основном, бесполезный метод init.Это может упростить добавление в подкласс первого поколения и автоматический вызов его версии -setup
, потому что он переопределяет метод no-op его родителя, если вы когда-нибудь решите, что стоит подкласс subclassOfMetrics
, вы собираетесьзакончить замену функциональной версии -setup
, или не забыть позвонить [super setup]
, чтобы получить функциональность, в любом случае победив цель вашего взлома.
Это, конечно, при условии, что вы этого не сделаливам нужно беспокоиться о добавлении новых ivars, что вы, конечно, делаете.
В том-то и дело, что функция -init
специально предназначена для инициализации иваров класса, а общее соглашение настроено так, что выесть только одна функция в каждом классе, в которой вы должны помнить, «выполнять действия в определенном порядке».Хорошо написанный ряд функций инициализации позволяет вам не беспокоиться о том, когда вызывать метод, такой как -setup
5 кадров глубже в стеке функций.Действующее соглашение «вызовите super's init, инициализируйте мои ivars, делайте посторонние настройки» существует, потому что оно гарантирует, что все настройки для класса выполняются в правильном порядке, независимо от того, сколько поколений в вашей иерархии заканчивается.
Код является шаблонным (хотя он и остается довольно минимальным), с единственными реальными решениями, которые вам необходимо принять, «если эта часть необходимой настройки войдет в init
, где она затронет всех детей или должнаперейти к функции -setup
, которая будет вызываться только один раз и будет очень специфична для моего класса? " (выделено жирным шрифтом для важности)
Затем, когда у вас будет хороший инициат, вы сможетесоздайте простой метод класса, который выглядит следующим образом:
+ (Metric*) newMetricWithFrame:(CGRect)frame {
Metrics* theMetric = [[self alloc] init]; //this will allow you to call it on whatever class you want and get the correct, fully initialized object
[theMetric setup]; //this will call the correct setup method
return theMetric;
}
Затем вы можете вызвать эту функцию следующим образом [subclassOfMetrics newMetricWithFrame:frame];
, и вы получите объект, который компилятор будет обрабатывать как Metric
, нокоторый будет отвечать на все вызовы метода как subclassOfMetrics
.Вы также можете привести возвращаемый результат, чтобы компилятор не жаловался на вызов для него методов, специфичных для подкласса:
subclassOfMetrics* theSub = (subclassOfMetrics*) [subclassOfMetrics newMetricWithFrame:frame];
[theSub subclassSpecificMethod];