重视我,每天共享一个关于 iOS 的新知识

前语

Swift 中的自界说运算符能够使代码更易于阅读和保护。必定程度上也能够让你编写更少的代码,同时保持逻辑明晰。

在 Swift 中开发代码时,咱们都经常运用默许运算符,比如运用 + 符号将两个数字相加,或许将两个字符串相加。今天来聊聊自界说运算符。

重载运算符

运算符重载允许在自界说类或结构体上运用已有的运算符(关于已有的运算符能够看文章底部的官网链接)。这是经过界说类型办法来完成的,这个类型办法的名称便是需求重载的运算符。

举个比如:

structVector2D{
varx=0.0,y=0.0
}
extensionVector2D{
staticfunc+(left:Vector2D,right:Vector2D)->Vector2D{
returnVector2D(x:left.x+right.x,y:left.y+right.y)
}
}
letvector1=Vector2D(x:1.0,y:2.0)
letvector2=Vector2D(x:3.0,y:4.0)
letvectorSum=vector1+vector2
print(vectorSum)//输出成果为Vector2D(x:4.0,y:6.0)

这个示例中,咱们重载了 “+” 运算符,让它能够用于 Vector2D 结构体。现在, “+” 运算符能够承受两个 Vector2D 实例作为参数,并回来一个新的 Vector2D 实例,这个实例的 x 和 y 值是参数的 x 和 y 值的和。

自界说运算符

除了重载运算符,还能够创建自己的自界说运算符。自界说运算符需求运用 operator 关键字进行声明,并需求指定它是一个前缀、中缀或后缀运算符。

这在很多开源项目中都有用到,比如 ObjectMapper 中的 <- 运算符:

infixoperator<-
publicfunc<-<T>(left:inoutT,right:Map){
switchright.mappingType{
case.fromJSONwhereright.isKeyPresent:
FromJSON.basicType(&left,object:right.value())
case.toJSON:
left>>>right
default:()
}
}

还有 >>> 运算符:

infixoperator>>>
publicfunc>>><T>(left:T,right:Map){
ifright.mappingType==.toJSON{
ToJSON.basicType(left,map:right)
}
}

运算符的三个类型

自界说运算符又分为三种类型,即:前缀、中缀和后缀。

1. 前缀运算符(Prefix Operator)

望文生义,这种运算符坐落操作数之前。用 prefix operator 来声明,如下面的比如中,界说了一个前缀运算符 ,用于取一个浮点数的平方根。

prefixoperator
prefixfunc(number:Double)->Double{
returnsqrt(number)
}
letnumber=4.0
print(number)//输出成果为2.0

2. 中缀运算符(Infix Operator)

这种运算符坐落两个操作数之间,这个也是平常最常用的。用 infix operator 来声明,如下面的比如中,界说了一个中缀运算符 **,用于进行乘方运算。

infixoperator**:MultiplicationPrecedence
func**(num:Double,power:Double)->Double{
returnpow(num,power)
}
letresult=2.0**3.0
print(result)//输出成果为8.0

3. 后缀运算符(Postfix Operator)

这种运算符坐落操作数之后。如下面的比如中,用 postfix operator 来声明,界说了一个后缀运算符 --,用于将一个整数减1。

postfixoperator--
postfixfunc--(num:inoutInt)->Int{
num-=1
returnnum
}
varnumber=5
print(number--)//输出成果为4

优先级

学会了自界说运算符后,你可能有个疑问,假如一个表达式中有多个运算符,应该先核算哪个后核算哪个?比如 1 + 2 * 3,在这个表达式中,乘法运算符 * 的优先级高于加法运算符 +,因此先进行乘法运算,再进行加法运算,终究成果是 7,而不是 9。

swift 中运用优先级组(precedencegroup)的概念来承认谁的优先级更高,根据 swift 内置的优先级组,优先级是这样摆放的:

BitwiseShiftPrecedence(位运算符组)> MultiplicationPrecedence(乘法运算符组)> AdditionPrecedence(加法运算符组)> RangeFormationPrecedence(区间运算符组)> CastingPrecedence > NilCoalescingPrecedence > ComparisonPrecedence > LogicalConjunctionPrecedence > LogicalDisjunctionPrecedence > TernaryPrecedence > AssignmentPrecedence

关于这些运算符组中都包括哪些运算符能够到苹果官方网站[1]中检查。

假如你自界说了一个新的运算符,并且想手动修正它的优先级,能够运用 precedencegroup 关键字来界说一个新的优先级组,然后在界说运算符时指定这个优先级组。优先级组能够设置以下几个特点:

  • higherThan:新的优先级组的优先级高于指定的优先级组。

  • lowerThan:新的优先级组的优先级低于指定的优先级组。

  • associativity:运算符的结合性,能够是 leftrightnone。假如运算符的优先级相同,那么结合性将决定运算的次序。

下面是一个比如:

precedencegroupExponentiationPrecedence{
higherThan:MultiplicationPrecedence
associativity:right
}
infixoperator**:ExponentiationPrecedence
func**(num:Double,power:Double)->Double{
returnpow(num,power)
}
letresult=2.0*3.0**2.0
print(result)//输出成果为18.0

这个示例中界说了一个新的优先级组 ExponentiationPrecedence,它的优先级高于乘法运算符的优先级组 MultiplicationPrecedence。然后界说了一个新的中缀运算符 **,并指定它的优先级组为 ExponentiationPrecedence。在核算 2.0 * 3.0 ** 2.0 这个表达式时,由于 ** 运算符的优先级高于 * 运算符,所以先核算 3.0 ** 2.0,得到成果 9.0,然后再与 2.0 相乘,得到成果 18.0。

参考资料

[1]

苹果官方网站: developer.apple.com/documentati…

这儿每天共享一个 iOS 的新知识,快来重视我吧

本文同步自微信大众号 “iOS新知”,每天按时共享一个新知识,这儿仅仅同步,想要及时学到就来重视我吧!