Reputation: 347
Consider the following class hierarchy in Swift:
GMSMarker is a class provided by the GoogleMaps library. It has two public initializers (one designated, one convenience).
MapItem, ClusterItem and Cluster are part of my model. I don't want to allow construction of MapItem objects; only ClusterItems and Clusters. Since Swift doesn't have abstract classes, having a private initializer would be sufficient for my purposes. However, given that MapItem inherits from GMSMarker with a convenience constructor, I can't simply override the designated initializer as private.
Given the rules of initializer inheritance in Swift, the only way that I've been able to prevent construction of the MapItem class is by declaring a new private initializer with a different signature so that the base class initializers aren't inherited.
class MapItem : GMSMarker {
private init(dummyParam: Int) {
super.init()
}
}
So far so good. Now, when trying to create my initializer for the ClusterItem class, I run into a problem.
class ClusterItem : MapItem {
weak var post: Post?
init(post: Post) {
self.post = post
super.init(dummyParam: 0)
}
}
I receive the following compiler error on the line that calls the super.init(): 'MapItem' does not have a member named 'init'
.
If I omit the call to super.init, I receive the following error: Super.init isn't called before returning from initializer
.
Is there any way of accomplishing what I want in swift. I would like to keep the inheritance hierarchy as is if possible because MapItem contains some common implementation code for ClusterItem and Cluster. Furthermore, I would like to be able to reference both ClusterItems and Clusters using a collection of MapItems.
Upvotes: 2
Views: 2341
Reputation: 130162
There are various ways to solve this issue:
Declare the initializer as internal
, that will give you module access and your subclass will be able to call it.
Declare the classes in the same file, then private
won't be an issue anymore (private
enables access from the same file).
Instead of abstract classes, you can make MapItem
a protocol
and ClusterItem
and Cluster
could inherit from GMSMarker
directly. However, this solution may not be good depending on your exact needs.
Upvotes: 1