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.
I think you are after a subclass of NSView
. Try this:
protocol TransmogrifiableView {
func transmogrify()
}
class MyNSView: NSView, TransmogrifiableView {
// do stuff.
}
And later in the code accept objects of type MyNSView
.
You maybe want an Extension
, see this
extension NSView: TransmogrifiableView {
// implementation of protocol requirements goes here
}
Yet another option is to make a class which holds a pointer to an NSView, and implements additional methods. This will also force you to proxy all methods from NSView that you want to use.
class NSViewWrapper: TransmogrifiableView {
var view : NSView!
// init with the view required.
// implementation of protocol requirements goes here.
.....
// proxy all methods from NSView.
func getSuperView(){
return self.view.superView
}
}
This is quite long and not nice, but will work. I would recommend you to use this only if you really cannot work with extensions (because you need NSViews without the extra method).