在Swift中限制类型的扩展?

3

我在Swift中有一个特定的类,希望限制创建扩展。我尝试添加final关键字,但它并不能限制创建扩展:

final class MyTest {
    func testFunc() {}
}

extension MyTest {
    func testFunc2() {}
}

let test = MyTest()
test.testFunc2()

这是可能的吗?

是的,它能正常工作,没有任何错误。 - Özgür Ersil
不可能的。 - Guilherme Torres Castro
去操场测试一下吧 :). 祝编码愉快。 - Tho Nguyen
我已经完成了。上面的代码来自游乐场,扩展程序可以正常工作。如果有“final”,我希望扩展程序不起作用。 - TruMan1
1个回答

3

您无法防止其他人向您的类添加扩展,就像您无法阻止另一个开发人员编写使用您的类的函数一样。

final修饰符仅可防止子类化。其他开发人员始终可以添加扩展。

这真的是个问题吗?

在我看来不是。

让我们来看看这个类:

final class Person {
    private let name: String
    func tellName() -> String { return "I am \(name)" }
    init(name: String) {
        self.name = name
    }
}

现在,另一位开发者可以编写(放到另一个源文件中)此功能。
func presentAndTellName(person: Person) {
    print("Hello everybody! \(person.tellName())")
}

这在一些不支持扩展的编程语言中也是可能的。这基本上是许多编程语言的工作方式之一,也是我们拥有访问控制(private、public等)的原因之一。
实际上,另一个开发人员无法使用我们类的私有属性/方法(除非他可以访问我们的源文件)。他也不能向Person添加属性,因为它是一个被标记为final的类,所以子类化是被禁止的。他只能编写使用它的代码。
我们都对此感到满意,对吧?
然而,编写一个仅接受参数并仅在该参数上工作的函数有时很丑陋。该函数应该是一个方法,参数值应该是实例。
因此,我们使用扩展来进行转换。
func presentAndTellName(person: Person) {
    print("Hello everybody! \(person.tellName())")
}

变成这样

extension Person {
    func presentAndTellName() {
        print("Hello everybody! \(self.tellName())")
    }
}

这只是一种编写相同逻辑并以OOP语法糖形式提供的方法。

现在,我们可以用以下方式来代替上述代码:

presentAndTellName(person)

我们可以写成这样

person.presentAndTellName()

使你的内容私有化

那么,如何保护你的类(/结构体)逻辑和数据不受扩展的影响?使用与保护源文件外部函数相同的机制,只需将它们标记为private。这样其他开发人员就无法在他们的扩展中使用它们。

让我们再次看一下我们的Person类。

class Person {
    private let name: String
    func tellName() -> String { return "I am \(name)" }
    init(name: String) {
        self.name = name
    }
}

name属性被标记为私有,因此没有办法让外部函数或扩展直接访问它。

等等,协议呢?

好的,也许这是扩展提供的唯一可以比更好的语法更多的东西。

实际上,考虑到这个协议:

protocol Runner {
    func run()
}

我们可以将一个我们不拥有的类适应它。
extension Person: Runner {
    func run() { print("") }
}

我想知道这背后的思考是什么,final 意味着最终! - TruMan1
3
@TruMan1:我可以问一下你试图解决的真正问题是什么吗? - Luca Angeletti
防止扩展与“final”无关。模块外的扩展只能使用公共属性和方法。要求语法myFunc(object)而不是object.myFunc并不能进一步实现封装目标。 - Rob Napier
1
@RobNapier:是的,这就是我在回答中的意思。 - Luca Angeletti
1
抱歉,回复TruMan1。你的答案完全正确。(我认为你在这些评论之后编辑了它以包括所有这些要点。) - Rob Napier
1
@RobNapier:是的,我认为这是澄清我们不必担心扩展程序的正确场所,因为它们不会将我们的私人信息置于风险之中。 - Luca Angeletti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接