斯威夫特语言指南显示,如下所示的运算符方法必须编写为static
struct Vector2D {
var x = 0.0, y = 0.0
}
extension Vector2D {
static func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
}
let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector
如果删除static
关键字,它将导致编译错误:
在“Vector2D”扩展中声明的运算符“+”必须是“静态”
提出这一要求的原因是什么?为什么我们不能把它写成一个非静态的方法呢?
我可以盲目地接受“这就是它的方式”。但是我想了解为什么这是必要的,这样我才能更好地理解Swift语言。我一直未能找到提出这项规定的具体原因。
如果我不得不猜测,我猜想Swift中的默认操作符是作为类型方法实现的,因此我们的自定义操作符也必须是静态的。但这纯粹是猜测。
发布于 2021-10-13 06:55:43
这对我来说很有道理。二进制运算符以两个对象作为参数,并返回结果。
这样的运算符不属于任何对象的实例。它是类中的一个静态方法。对于+
类型的Vector2D
方法的示例,它是一个知道如何将2个Vector2D
对象添加到一起的方法。
您不会在+
实例上调用Vector2D
方法。您说:“嗨,Vector2D
类型,我如何将您的类型的两个实例相加?
您是在“与”类“交谈”,而不是类的实例。
编辑:
如果是实例方法,则必须将add操作符表示为一个操作数的消息:
extension Vector2D {
func addVector(_: Vector2D) -> Vector2D {
// Code to sum two vectors
}
}
你会把它叫做
sum = aVector.addVector(anotherVector)
发布于 2021-10-13 07:09:41
这是一种语言设计选择,不同的语言决定了不同的对立面: C++不允许静态运算符,而C#要求它们是静态的,就像Swift一样。
对我来说,让操作符静止的最令人信服的理由是对称。
让我们暂时将+
替换为名为plus
的函数。如果plus
是静态的,则将其称为Vector2D.plus(vector, anotherVector)
,这将与调用Vector2D.plus(anotherVector, vector)
相同。
如果它是实例成员,则将其称为vector.plus(anotherVector)
,这可能与anotherVector.plus(vector)
相同,也可能不相同。也就是说,如果vector
是nil
,则vector.plus(anotherVector)
肯定是nil
,而anotherVector.plus(vector)
将等于anotherVector
。
类似地,操作符+
是静态的,允许这个vector + anotherVector == anotherVector + vector
,而不考虑两个向量的nil
状态。
发布于 2021-10-13 08:41:20
操作人员不必是静态的。它们也可以是全局函数。
struct Vector2D {
var x = 0.0, y = 0.0
}
func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector
如果您问为什么它们不能是实例方法,那么,因为实例方法需要一个额外的Vector2D
实例来调用。这个实例,加上+
需要的两个参数,意味着您需要3个Vector2D
来调用+
,这没有多大意义.
另一方面,营办商可能是这样设计的:
extension Vector2D {
func +(right: Vector2D) -> Vector2D { ... }
}
其中,二进制运算符不是对两个参数进行操作,而是在self
和单个参数上操作。这与Kotlin的操作符重载设计类似。
据我所见,Swift中没有任何东西能阻止Swift被设计成这样。其原因很可能是美学,如邓肯C所建议的“有两个参数更有意义”,而有两个参数也更清楚哪些是左操作数,哪些是右操作数。
https://stackoverflow.com/questions/69557225
复制