I\'m creating several NSView
classes, all of which support a special operation, which we\'ll call transmogrify
. At first glance, this seems like t
For Swift 4, based on @Antoine's keen insight:
Create a protocol then use a typealias to give a cleaner name to a type that conforms to both a class and the protocol.
protocol Transmogrifiable {
func transmogrify()
}
typealias TransmogrifiableView = NSView & Transmogrifiable
You can then define a class that inherits from that type....
class ATransmogView: TransmogrifiableView {
func transmogrify() {
print("I'm transmogging")
}
}
....or define a class that inherits from the protocol and a subclass
// this also qualifies as a TransmogrifiableView
class BTransmogView: NSTextView, Transmogrifiable {
func transmogrify() {
print("I'm transmogging too")
}
}
Now you can do this.
func getTransmogrifiableView() -> TransmogrifiableView {
return someBool ? ATransmogView() : BTransmogView()
}
And this now compiles.
let myView: TransmogrifiableView = getTransmogrifiableView()
let theSuperView = myView.superView
Still not the ideal solution, but here's a pattern I use on occasion:
This let's your base class call the protocol methods while forcing the children to implement them (eg. self.myDelegate?.myProtocolMethod).
As per definition a protocol just declares requirements of "methods, properties an other requirements". And by "other requirements" it means a superclass is not a part of it.
A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality.
Right now, I don't see a clean solution. It's possible to use a where
-clause to define a type which is a NSView
and conforms to the TransmogrifiableView
like this:
class MyClass<T where T: NSView, T: TransmogrifiableView> {
var aTransmogrifiableNSView: T
}
Or you could use another superclass:
protocol TransmogrifiableViewProtocol {
func transmogrify()
}
class TransmogrifiableView: NSView, TransmogrifiableViewProtocol {
func transmogrify() {
assert(false, "transmogrify() must be overwritten!")
}
}
class AnImplementedTransmogrifiableView: TransmogrifiableView {
func transmogrify() {
println("Do the transmogrification...")
}
}
In the end both solutions aren't clean and wouldn't satisfy myself. Maybe an abstract
-keyword will be added to Swift someday?
You could use something like this:
protocol TransmogrifiableView where Self:NSView {}
This requires all created instances which one conforms to TransmogrifiableView protocol to be subclassed with NSView
Starting from Swift 4 you can now define this as followed:
let myView: NSView & TransmogrifiableView
For more information, checkout issue #156 Subclass Existentials
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).