In Swift, how do I prevent a function from being called on a subclass?
Disclaimer
The protocol version would probably be better design - see the Leskov Substitution Principle amount the other things you mentioned.
Answering the question
You can use the attribute @available()
(see Swift -> Language Reference -> Attributes).
class Parent {
func doThis() { print("Parent Did This") }
func doThat() { print("Parent Did That") }
}
class Child: Parent {
override func doThis() {
print("Child Did This")
}
@available(*, unavailable, message:"Child can't doThat")
override func doThat() {
print("Not Supported")
}
}
let parent = Parent()
parent.doThis()
parent.doThat()
let child = Child()
child.doThis()
child.doThat()
You get the following error message on child.doThat()
:
'doThat()' is unavailable: Child can't doThat
However you can get around this by doing the following (again, see Liskov substitution principle):
let maybeChild: Parent = Child()
maybeChild.doThis()
maybeChild.doThat()
I'd handle this using @availability
. Something like:
@available(*, deprecated=1.0, message="Do not call this method")
final func foo(){ //function you want to protect
}
This will give you a compiler warning any time you call the function.
Interestingly, marking the function as unavailable
will throw a compiler error, making it impossible to build the app if anyone calls this function. Unfortunately, there is no way to suppress that error in Swift, so that will break it for your good use cases as well. Maybe you can get around this by using self.performSelector("foo")
.
Also note I marked foo()
as final
, which prevents it from being overridden by a subclass.