Swift传统上重视语法的清晰性,允许用户创建自定义运算符(运算符重载),包括新的符号甚至关键字。这扩展了DSL的能力,使代码非常富于表现力。
如果不理解运算符声明的原则,可能会导致模棱两可、可读性差和难以维护的代码。错误选择优先级或关联性会导致意外结果。如果不指定限制,编译器允许创建非常“危险”的表达式。
可以声明新的infix、prefix、postfix运算符,指定它们的优先级和适用范围。示例:
infix operator ~> : AdditionPrecedence func ~> (lhs: Int, rhs: Int) -> Int { return lhs * 10 + rhs } let x = 2 ~> 3 // 23
对于自定义优先级,需要声明:
precedencegroup MyPrecedence { associativity: left higherThan: AdditionPrecedence } infix operator *** : MyPrecedence
关键特点:
实现函数和运算符声明是必需的吗?
是的,如果声明了运算符,需要实现相应的函数,否则会出现编译器错误。函数的签名与运算符的签名相同。
如何正确选择precedencegroup,以及group如何影响计算顺序?
precedencegroup定义了运算符的计算优先级和关联性。错误选择group可能会导致在包含多个运算符的表达式中出现意外结果(例如,乘法/加法和您的自定义运算符)。
可以声明带有文本名称的自定义运算符吗?
不可以,自定义运算符只能通过特定的符号或Swift语法定义的序列来访问。文本标准名称不允许作为运算符声明。
在一个项目中,为奇怪的集合转换声明了运算符<<<和>>>,没有描述优先级、关联性和文档。新员工不理解他们所做的以及表达式的计算顺序。
优点:
缺点:
在一个项目中使用自定义运算符=>进行声明式构建可链式的pipeline(例如,在UI构建器中),明确描述了优先级并有文档实现。每个开发者都理解自己所做的以及其用法。
优点:
缺点: