I'm creating several NSView
classes, all of which support a special operation, which we'll call transmogrify
. At first glance, this seems like the perfect place for a protocol:
protocol TransmogrifiableView { func transmogrify() }
However, this protocol does not enforce that every TransmogrifiableView
be an NSView
as well. This means that any NSView
methods I call on a TransmogrifiableView
will not type check:
let myView: TransmogrifiableView = getTransmogrifiableView() let theSuperView = myView.superView // error: TransmogrifiableView does not have a property called 'superview'
I don't know how to require that all classes implementing my protocol are also subclasses of NSView
. I tried this:
protocol TransmogrifiableView: NSView { func transmogrify() }
but Swift complains that protocols cannot inherit from classes. It does not help to turn the protocol into a class-only protocol using
protocol TransmogrifiableView: class, NSView { func transmogrify() }
I cannot make TransmogrifiableView
a superclass rather than a protocol, because some of my TransmogrifiableView
classes must be subclasses of other, non-transmogrifiable views.
How should I require that all TransmogrifiableView
's also be NSView
's? I really don't want to pepper my code with "as
" conversions, which are bad form and distracting.
Subclassing. Subclassing is the act of basing a new class on an existing class. The subclass inherits characteristics from the existing class, which you can then refine. You can also add new characteristics to the subclass.
In Swift, to use a protocol, other classes must conform to it. After we conform a class to the protocol, we must provide an actual implementation of the method.
Protocols allow you to group similar methods, functions, and properties. Swift lets you specify these interface guarantees on class , struct , and enum types. Only class types can use base classes and inheritance from a protocol.
Swift 4 allows multiple protocols to be called at once with the help of protocol composition.
Update. In the latest Swift version you can just write
protocol TransmogrifiableView: NSView { func transmogrify() }
, and this will enforce the conformer types to be either NSView
, or a subclass of it. This means the compiler will "see" all members of NSView
.
Original answer
There is a workaround by using associated types to enforce the subclass:
protocol TransmogrifiableView { associatedtype View: NSView = Self func transmogrify() } class MyView: NSView, TransmogrifiableView { ... } // compiles class MyOtherClass: TransmogrifiableView { ... } // doesn't compile
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With