2015-08-19 3 views
0

У меня есть базовый класс с двумя методами init - один из них обозначается списком параметров, другой представляет собой удобную инициализацию, которая получает значения параметров из NSDictionary (который используется для сериализации объектов). Все хорошо, пока я не попытаюсь создать подкласс - удобство init создает ошибку, если я попытаюсь вызвать соответствующий super.init (...) и требует, чтобы я назвал назначенный init подкласса. Суперкласс содержит ключи, используемые для извлечения значений параметров, и я не хочу дублировать код или иметь значения открытого ключа.Быстрый подкласс init tangle

Я мог бы установить фиктивные значения и использовать отдельный метод loadFromDict() (который затем может быть переопределен), но это кажется неудобным. Есть ли другой способ?

+0

Пример кода (минимальный) был бы полезен ... –

+0

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

ответ

0

Ошибка, которую вы видите, является нормальной, как если бы она следовала правилам инициализации в Swift. Удобный init всегда должен вызывать другой init в том же классе. Другой init может быть другим удобством, или он может быть назначен. В какой-то момент, хотя назначенный init нужно вызвать в подклассе, прежде чем он вызовет суперкласс. Swift обеспечивает, чтобы только назначенный init мог вызвать супер-класс init. Это из Swift Language reference

Для упрощения отношений между назначенными и удобством инициализаторами, Swift применяет следующие три правил для делегирования вызовов между инициализаторами:

Правилом 1

Назначенным инициализатором должен вызывать назначенный инициализатор из своего непосредственного суперкласса.

Правило 2

Удобный инициализатор должен вызвать другой инициализатор из того же класса.

Правило 3

Удобный инициализатор должен в конечном счете вызвать обозначенный инициализатор.

Простой способ запомнить это:

Назначенные Инициализаторы всегда должен делегировать вверх.

Инициализаторы удобства всегда должны делегировать друг другу.

0

Эта часть the apple docs также может быть полезной:

Предполагая, что вы предоставите значения по умолчанию для всех новых свойств, которые вы представить в подклассе, следующие два правила:

Правило 1

Если ваш подкласс не определяет какие-либо назначенные инициализаторы, он автоматически наследует все его инициализаторы, назначенные суперклассам.

Правило 2

Если подкласс обеспечивает реализацию всех его суперкласса назначенный инициализаторах-либо унаследовать их согласно правилу 1, или путем предоставления пользовательской реализации в рамках своего определения, то он автоматически наследует все инициализаторов удобства суперкласса.

Эти правила применяются, даже если ваш подкласс добавляет дополнительные инициализаторы удобства.

ПРИМЕЧАНИЕ

Подкласс может реализовать суперкласс обозначенного инициализатору как удобство подкласс инициализатор как часть удовлетворяющего правилу 2.

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

Вот как это может выглядеть:

Superclass:    DesignatedInit ConvenienceInit 
           |  /
          (override) / // ConvenienceInit 
           |  / // will call overridden 
           | / // designated initializer 
Subclass:    DesignatedInit  // in subclass. 
0

В конце концов, я сделал суперкласса удобство инициализации в назначенный один и дублируется код из других указанных инициализации, который, кажется, единственный способ для вызова его из подкласса. Добавление метода 'setup', который можно было бы назвать позже, означало введение опций, которые путали код.

Чтобы уточнить мой вопрос, я хотел подклассифицировать удобство init, чтобы я мог вызвать super.init (...), а также сделать некоторые вещи, относящиеся к подклассам. Теперь это тривиально, что делает его назначенным init, но это означает, что два назначенных inits не могут передавать код обработки, что неудобно.

Я ценю, что проект Swift init предназначен для защиты кодировщиков от введения ошибок, но временами он чувствует себя слишком негибким.

BTW Я ценю полезное намерение, но публикация кусков документации не идеальна - просто ссылка в порядке.

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