购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

Tip 7

操作符

与Objective-C不同,Swift支持重载操作符,它的最常见的使用方式可能就是定义一些简便的计算了,比如我们需要一个表示二维向量的数据结构:

一个很简单的需求是两个Vector2D相加:

如果只做一次的话似乎还好,但是一般情况下我们会进行多次这种操作。这样的话,我们可能更愿意定义一个Vector2相加的操作,来简化代码使其更清晰。

对于两个向量相加,我们可以重载加号操作符:

这样,上面的v3以及之后的所有表示两个向量相加的操作,就全部可以用加号来表达了:

类似地,我们还可以为Vector2D定义像-(减号,表示两个向量相减)、-(负号,表示单个向量x和y同时取负)等这样的运算符。这个就作为练习交给大家。

上面定义的加号、减号和负号都是已经存在于Swift中的运算符了,我们所做的只是变换它的参数进行重载。如果我们想定义一个全新的运算符,要做的事情会多一件。比如 点积 运算 就是一个在矢量运算中很常用的运算符,它表示两个向量对应坐标的乘积的和。根据定义,并参考重载运算符的方法,我们选取+*来表示这个运算,不难写出:

但是编译器会返给我们一个错误:

Operator implementation without matching operator declaration

这是因为我们没有对这个操作符进行声明。之前可以直接重载像+、-、*这样的操作符,是因为它们在Swift中已经有定义了,如果我们要新加操作符的话,需要先对其进行声明,告诉编译器这个符号其实是一个操作符。我们来添加如下代码:

infix

表示要定义的是一个中位操作符,即前后都是输入;其他的修饰子还包括prefix和postfix,不再赘述。

associativity

定义了结合律,即多个同类的操作符顺序出现时的计算顺序。比如常见的加法和减法都是left,就是说多个加法同时出现时按照从左往右的顺序计算(因为加法满足交换律,所以这个顺序无所谓,但是减法的话计算顺序就很重要了)。点乘的结果是一个Double,不会再和其他点乘结合使用,所以这里写成none。

precedence

表示运算的优先级,越高越优先进行运算。Swift中乘法和除法的优先级是150,加法和减法是140,这里我们定义点积的优先级为160,就是说它应该优先于普通的乘除法进行运算。

有了这些之后,我们就可以很简单地进行向量的点积运算了:

最后需要多提一点的是,Swift的操作符是不能定义在局部域中的,因为一个操作符至少要能在全局范围使用,否则也就失去意义了。另外,来自不同module的操作符是有可能产生冲突的,这对于库开发者来说是需要特别注意的地方。如果库中的操作符冲突,使用者是无法像解决类型名冲突那样通过指定库名字来进行调用的。因此在重载或者自定义操作符时,应当尽量将其作为其他某个方法的“简便写法”,而避免在其中实现大量逻辑或者提供独一无二的功能。这样即使出现了冲突,使用者也可以通过方法调用的方式使用你的库。运算符的命名也应当尽量明了,避免歧义和可能的误解。因为一个不被公认的操作符是存在冲突风险和理解难度的,所以我们不应该滥用这个特性。在使用重载或者自定义操作符时,请先再三权衡斟酌,你或者你的用户是否真的需要这个操作符。 eWcA9q3ugkahN8Tj3t4H+eLNytTIHwnLoYk5roJI4eV4NZVwVtd7RC+DCdWHNk7k

点击中间区域
呼出菜单
上一章
目录
下一章
×