diff --git a/source/chapter3/05_Declarations.md b/source/chapter3/05_Declarations.md index 257b7c96..21176915 100755 --- a/source/chapter3/05_Declarations.md +++ b/source/chapter3/05_Declarations.md @@ -535,6 +535,14 @@ func someFunction(callback: () throws -> Void) rethrows { 抛出方法不能重写重抛方法,而且抛出方法不能满足协议对于重抛方法的要求。也就是说,重抛方法可以重写抛出方法,而且重抛方法可以满足协议对于抛出方法的要求。 + +### 永不返回的函数 + +Swift定义了`Never`类型,它表示函数或者方法不会返回给它的调用者。`Never`返回类型的函数或方法可以称为不归,不归函数、方法要么引发不可恢复的错误,要么永远不停地运作,这会使调用后本应执行得代码就不再执行了。但即使是不归函数、方法,抛错函数和重抛出函数也可以将程序控制转移到合适的`catch`代码块。 + +不归函数、方法可以在guard语句的else字句中调用,具体讨论在[*Guard语句*](10_Statement.md#guard_statements)。 +你可以重载一个不归方法,但是新的方法必须保持原有的返回类型和没有返回的行为。 + > 函数声明语法 @@ -571,6 +579,9 @@ func someFunction(callback: () throws -> Void) rethrows { > > *默认参数子句* → **=** [*表达式*](04_Expressions.md#expression) + + + ## 枚举声明 @@ -1146,21 +1157,12 @@ subscript (参数列表) -> 返回类型 { 下面的形式声明了一个新的中缀运算符: ```swift -infix operator 运算符名称 { - precedence 优先级 - associativity 结合性 -} +infix operator 运算符名称: 优先级组 ``` 中缀运算符是二元运算符,置于两个运算对象之间,例如加法运算符(`+`)位于表达式 `1 + 2` 的中间。 -中缀运算符可以选择指定优先级或结合性,或者两者同时指定。 - -运算符的优先级可以指定在没有括号包围的情况下,运算符与其运算对象如何结合。可以使用上下文相关的关键字 `precedence` 以及紧随其后的优先级数字来指定一个运算符的优先级。优先级可以是 `0` 到 `255` 之间的任何十进制整数。与十进制整数字面量不同的是,它不可以包含任何下划线字符。尽管优先级是一个特定的数字,但它仅用作与另一个运算符的优先级比较大小。也就是说,当两个运算符为同一个运算对象竞争时,例如 `2 + 3 * 5`,优先级更高的运算符将优先参与运算。 - -运算符的结合性可以指定在没有括号包围的情况下,多个优先级相同的运算符将如何组合。可以使用上下文相关的关键字 `associativity` 以及紧随其后的结合性关键字来指定运算符的结合性,结合性关键字也是上下文相关的,包括 `left`、`right` 和 `none`。左结合运算符以从左到右的顺序进行组合。例如,减法运算符(`-`)具有左结合性,因此 `4 - 5 - 6` 以 `(4 - 5) - 6` 的形式组合,其结果为 `-7`。右结合运算符以从右到左的顺序组合,而设置为 `none` 的运算符不进行组合。具有相同优先级的非结合运算符,不可以互相邻接。例如,表达式 `1 < 2 < 3` 是非法的。 - -声明时不指定任何优先级或结合性的中缀运算符,优先级为 `100`,结合性为 `none`。 +中缀运算符可以选择指定优先级组。如果没有为运算符设置优先级组,Swift会设置默认优先级组`DefaultPrecedence`,它的优先级比三目优先级`TernaryPrecedence`要高,更多内容参考[*优先级组声明*](#precedence_group_declaration_modifiers) 下面的形式声明了一个新的前缀运算符: @@ -1197,18 +1199,62 @@ postfix operator 运算符名称 {} > > *中缀运算符声明* → **infix** **运算符** [*运算符*](02_Lexical_Structure.md#operator) **{** [*中缀运算符属性*](#infix-operator-attributes)可选 **}** - -> *中缀运算符属性* → [*优先级子句*](#precedence-clause)可选 [*结和性子句*](#associativity-clause)可选 -> -> *优先级子句* → **precedence** [*优先级水平*](#precedence-level) -> -> *优先级水平* → 十进制整数 0 到 255,包含 0 和 255 -> -> *结和性子句* → **associativity** [*结和性*](#associativity) -> -> *结和性* → **left** | **right** | **none** + +> *中缀运算符组* → [*优先级组名称*](#precedence-group-name) + + + + +## 优先级组声明 + +*优先级组声明 (A precedence group declaration)* 会向程序的中缀运算符引入一个全新的优先级组。当没有用圆括号分组时,运算符优先级反应了运算符与它的操作数的关系的紧密程度。 +优先级组的声明如下所示: + +```swift +precedencegroup 优先级组名称{ + higherThan: 较低优先级组的名称 + lowerThan: 较高优先级组的名称 + associativity: 结合性 + assignment: assignment +} +``` +较低优先级组和较高优先级组的名称说明了新建的优先级组是依赖于现存的优先级组的。 `lowerThan`优先级组的属性只可以引用当前模块外的优先级组。当两个运算符为同一个操作数竞争时,比如表达式`2 + 3 * 5`,优先级更高的运算符将优先参与运算。 + +> 注意 +> 使用较低和较高优先级组相互联系的优先级组必须保持单一层次关系,但它们不必是线性关系。这意味着优先级组也许会有未定义的相关优先级。这些优先级组的运算符在没有用圆括号分组的情况下是不能紧邻着使用的。 + +Swift定义了大量的优先级组来与标准库的运算符配合使用,例如相加(`+`)和相减(`-`)属于`AdditionPrecedence`组,相乘(`*`)和相除(`/`)属于` MultiplicationPrecedence`组,详细关于Swift标准库中一系列运算符和优先级组内容,参阅[Swift标准库操作符参考](https://developer.apple.com/reference/swift/1851035-swift_standard_library_operators)。 + +运算符的结合性用于表示在没有圆括号分组的情况下,同样优先级的一系列运算符是如何被分组的。你可以指定运算符的结合性通过上下文关键字`left`、`right`或者`none`,如果没有指定结合性,默认是`none`关键字。左关联性的运算符是从左至右分组的,例如,相减操作符(-)是左关联性的,所以表达式`4 - 5 - 6`被分组为`(4 - 5) - 6`,得出结果-7。右关联性的运算符是从右往左分组的,指定为`none`结合性的运算符就没有结合性。同样优先级没有结合性的运算符不能相邻出现,例如`<`运算符是`none`结合性,那表示`1 < 2 < 3`就不是一个有效表达式。 + +优先级组的`assignment`表示在包括可选链的操作时的运算符优先级。当设为true时,与优先级组对应的运算符在可选链操作中使用和标准库中赋值运算符同样的分组规则,当设为false或者不设置,该优先级组的运算符与不赋值的运算符遵循同样的可选链规则。 + + +> 优先级组声明语法 + + +> *优先级组声明* → **precedence**[*优先级组名称*](#precedence-group-name){[*多优先级组属性*](#precedence-group-attributes)可选 } + +> *优先级组属性* → [*优先级组属性*](#precedence-group-attribute)[*多优先级组属性*](#precedence-group-attributes)可选 **{** **}** + +> *优先级组属性* → [*优先级组关系*](#precedence-group-relation) +> *优先级组属性* → [*优先级组赋值性*](#precedence-group-assignment) +> *优先级组属性* → [*优先级组相关性*](#precedence-group-associativity) +> +> *优先级组关系* → **higherThan:**[*多优先级组名称*](#precedence-group-names) +> *优先级组关系* → **lowerThan:**[*多优先级组名称*](#precedence-group-names) +> +> *优先级组赋值* → **assignment:**[*布尔字面值*](02_Lexical_Structure.md#boolean-literal) + +> *优先级组结合性* → **associativity:left** +> *优先级组结合性* → **associativity:right** +> *优先级组结合性* → **associativity:none** + +> *多优先级组名称* → [*优先级组名称*](#precedence-group-name) | [*优先级组名称*](#precedence-group-name) | [*优先级组名称*](#precedence-group-name) + +> *优先级组名称* →[*标识符*](02_Lexical_Structure.md#identifier) + - ## 声明修饰符 声明修饰符都是关键字或上下文相关的关键字,可以修改一个声明的行为或者含义。可以在声明的特性(如果存在)和引入该声明的关键字之间,利用声明修饰符的关键字或上下文相关的关键字指定一个声明修饰符。