2015-09-30 3 views
1

Рассмотрим следующую иерархию классов в Swift:Наследовать от класса с помощью частного инициализатора?

Class Hierarchy

GMSMarker класс предоставляются библиотекой GoogleMaps. Он имеет два открытых инициализатора (один назначенный, одно удобство).

MapItem, ClusterItem и Cluster являются частью моей модели. Я не хочу разрешать создание объектов MapItem; только ClusterItems и Clusters. Так как Swift не имеет абстрактных классов, для меня будет достаточно частного инициализатора. Однако, учитывая, что MapItem наследует GMSMarker с помощью конструктора удобства, я не могу просто переопределить назначенный инициализатор как закрытый.

Учитывая правила наследования инициализатора в Swift, единственный способ предотвратить создание класса MapItem - это объявить новый закрытый инициализатор с другой подписью, чтобы инициализаторы базового класса не были унаследованы ,

class MapItem : GMSMarker { 

    private init(dummyParam: Int) { 
     super.init() 
    } 
} 

Пока все хорошо. Теперь, пытаясь создать мой инициализатор для класса ClusterItem, я столкнулся с проблемой.

class ClusterItem : MapItem { 

    weak var post: Post? 

    init(post: Post) { 
     self.post = post 
     super.init(dummyParam: 0) 
    } 
} 

Я получаю следующее сообщение об ошибке компилятора на линии, которая вызывает super.init(): 'MapItem' does not have a member named 'init'.

Если я опускаю вызов super.init, я получаю следующую ошибку: Super.init isn't called before returning from initializer.

Есть ли способ выполнить то, что я хочу в быстром. Я хотел бы сохранить иерархию наследования, если это возможно, потому что MapItem содержит некоторый общий код реализации для ClusterItem и Cluster. Кроме того, я хотел бы иметь возможность ссылаться на ClusterItems и Clusters, используя коллекцию MapItems.

+1

Сделать его «внутренним», а не «частным». Или объявите классы в одном файле, тогда 'private' не будет проблемой. – Sulthan

+0

Спасибо @Sulthan, объявив классы в том же файле. Исходя из мира C++/C#, управление доступом Swift занимает некоторое время, чтобы привыкнуть. – Dragonspell

ответ

1

Существуют различные способы решения этой проблемы:

  1. Declare инициализатор, как internal, что даст вам модуль доступа и ваш подкласс будет в состоянии назвать его.

  2. Объявить классы в одном файле, тогда private больше не будет проблемой (private разрешает доступ из того же файла).

  3. Вместо абстрактных классов, вы можете сделать MapItem в и ClusterItem и Cluster могли наследовать от GMSMarker непосредственно. Однако это решение может быть не очень хорошим в зависимости от ваших конкретных потребностей.

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