I have a specific class in Swift that I would like to restrict extensions from being created. I tried adding the final
keyword, but it does not restrict extensions:
final class MyTest {
func testFunc() {}
}
extension MyTest {
func testFunc2() {}
}
let test = MyTest()
test.testFunc2()
Is this possible?
You cannot prevent someone from adding an extension to your class. Like you cannot prevent another developer from writing a function that uses your class.
The
final
modifier only prevents subclassing. Other developers will always be able to add extensions.
IMHO it is not.
Let's look at this class
final class Person {
private let name: String
func tellName() -> String { return "I am \(name)" }
init(name: String) {
self.name = name
}
}
Now another developer could write (into another source file) this function
func presentAndTellName(person: Person) {
print("Hello everybody! \(person.tellName())")
}
This is possible in several other programming languages that don't support extensions. Well it's basically how many programming languages work and it's one of the reasons why we have access control (private, public, ...).
Another developer infact cannot use private
properties/methods of our class (unless it has access to our source file). He also cannot add properties to Person
because it's a class marked as final
so subclassing is offlimits. He can only write code that use it.
We all are fine with this right?
However writing a function that accepts a parameter and work only on that param sometimes is ugly. The function should be a method and the parameter value should be the instance.
So we use extensions to convert this
func presentAndTellName(person: Person) {
print("Hello everybody! \(person.tellName())")
}
into this
extension Person {
func presentAndTellName() {
print("Hello everybody! \(self.tellName())")
}
}
It's only a way of writing the same logic and making it available in a OOP syntax sugar.
Now instead of writing this
presentAndTellName(person)
we can write this
person.presentAndTellName()
So how can you protect some of your class (/struct) logic and data from extensions? With the same mechanism you use to protect this stuff from functions external to your source file, just mark them private
. This way other developers won't be able to use them into their extensions.
Let's look again at our Person class.
class Person {
private let name: String
func tellName() -> String { return "I am \(name)" }
init(name: String) {
self.name = name
}
}
The name
property is market as private so there is no way and external function or an extension will be able to directly access it.
Ok, this is maybe the only thing where extensions offer something more than a better syntax.
Infact given this protocol
protocol Runner {
func run()
}
we can conform to it a class we don't own
extension Person: Runner {
func run() { print("š") }
}