还有其他语言有类似Swift';s扩展?

还有其他语言有类似Swift';s扩展?,swift,methods,swift-extensions,member-functions,Swift,Methods,Swift Extensions,Member Functions,在Swift中,扩展是一种事后为类定义成员的方法。或者,你可以说,这是(来自一个新手)编写函数的奇特方式: extension Double { var mm: Double { return self * 1_000.0 } func mm1() -> Double { return self * 1_000.0 } } func mm(a: Double) -> Double { return a * 1_000.0 } print("One mete

在Swift中,扩展是一种事后为类定义成员的方法。或者,你可以说,这是(来自一个新手)编写函数的奇特方式:

extension Double {
    var mm: Double { return self * 1_000.0 }
    func mm1() -> Double { return self * 1_000.0 }
}

func mm(a: Double) -> Double {
    return a * 1_000.0
}

print("One meter is \(1.mm) milimeters")
print("One meter is \(1.mm1()) milimeters")
print("One meter is \(mm(1)) milimeters")

我从未见过这样的事。在其他语言中有类似的东西吗?

这叫做猴子补丁。有一些其他语言支持它,比如Ruby

是的,其他语言也有扩展之类的特性。正如@hnh指出的那样

它还清楚地表明,此功能不是“猴子修补”

扩展方法是一种特殊的静态方法,但它们被调用时就好像它们是扩展类型上的实例方法一样

换句话说,扩展更像是一种语法糖。给出问题中的例子,Double,您可以创建一个接受Double的函数(如问题所示)

然后你可以直接打电话给它

var foo = 12.34;
print("One meter is \(mm(foo)) millimeters")
C#和Swift中的扩展都会有效地告诉编译器在幕后进行翻译

someDouble.mm()
进入

或者在我们的例子中更像

__extension_for_type_Double_mm(someDouble as self)
所以,什么都没有修补

这也意味着您可以从不同的模块中拥有多个
mm
扩展名,并通过仅在该文件中导入该模块来选择每个文件要使用的扩展名,而其他一些文件可以为具有相同名称的相同类型导入具有另一扩展名的另一个模块。这在monkey修补中是不可能的,因为对象或其类/原型被修补(实际上有些东西发生了变化)。在这里,没有什么变化,只是调用独立函数的语法糖


这意味着Ruby和JavaScript中的monkey patching等功能与扩展不同。

C#也有类似之处:您可以使用其原型来扩充JavaScript类(但强烈不建议使用数组等内置功能)。或者更直接地说,我相信随着Go的结构化,不可能以任何其他方式定义方法。如果你在C语言中使用一些函数来操作结构(这是一种面向对象的方法,没有华丽的语法),那么类似的原则也适用于C语言。如果你愿意,这是一种几乎可以在任何语言中使用的模式。哦,当然Smalltalk和ObjC可以通过类别来实现。尽管它们的工作方式不同于Swift扩展(它们是monkey-patch;-)@Dave我知道JS,但我认为它不重要,因为它没有真正的类,而是原型。C没有任何像class.ahem那样封装功能的东西(请特别参阅第二个答案)。只是因为它没有一个好的语法,并不意味着你做不到。我非常怀疑任何人都会认为Swift扩展是猴子补丁。它们是独立的扩展,除非将定义它们的模块导入编译单元,否则它们甚至不会生效。这与人们在JavaScript、ObjC和Ruby中所做的猴子补丁大不相同。@hnh我不认为被隔离或不被隔离会改变定义。它看起来像猴子,工作起来像猴子,那么它就是猴子。它可能是猴子,但关键是它不是补丁;-)我认为monkey补丁的关键方面是修改语言的动态运行时以替换或添加方法。例如,重新定义JS对象的键与新函数的绑定,或者通过ObjC中的方法swizzling执行类似的操作。快速扩展不是这样的。没有任何东西被修补,所有东西都被干净地分开,没有猴子在周围游荡。查看@hnh的细节是正确的。这不是一个猴子补丁。相反,它是类型特定函数的语法糖。换句话说,上面的示例有效地创建了一个函数
\uuuuuumm
,然后当它看到
someDouble.mm()
时,它将其转换为类似
\uuuuuumm(someDouble作为self)
。什么都没有补上。没有猴子。我熟悉Ruby/JavaScript中的猴子补丁,并试图找出它是否与Swift中的扩展相同。事实证明它是不同的(更像是lisp中的宏!)谢谢!在Swift中,扩展可以使类型符合协议(类似于C#接口)。这被称为“追溯一致性”。C#有类似的东西吗?(我知道原来的问题没有问这个。)链接的C#docs展示了一个使用C#extensions符合接口的示例,哪个示例是这样的?我在链接页面中看到的唯一接口是
IMyInterface
,所有符合它的类(
A
B
、和
C
)都直接在它们的声明中这样做。你可能应该问一个C标记的问题,显示你在swift中能够实现什么,并询问如何在C中实现同样的目标。评论不是讨论这个问题的好地方。
mm(someDouble)
__extension_for_type_Double_mm(someDouble as self)