diff --git a/swift-6-beta.docc/ReferenceManual/Declarations.md b/swift-6-beta.docc/ReferenceManual/Declarations.md index 444706ba..242feebc 100644 --- a/swift-6-beta.docc/ReferenceManual/Declarations.md +++ b/swift-6-beta.docc/ReferenceManual/Declarations.md @@ -1,27 +1,12 @@ - - -# Declarations +# 声明 -Introduce types, operators, variables, and other names and constructs. +引入类型、运算符、变量以及其他名称和构造。 -A *declaration* introduces a new name or construct into your program. -For example, you use declarations to introduce functions and methods, -to introduce variables and constants, -and to define enumeration, structure, class, and protocol types. -You can also use a declaration to extend the behavior -of an existing named type and to import symbols into your program that are declared elsewhere. +*声明*将在程序中引入一个新的名称或构造例如,你使用声明来引入函数和方法,引入变量和常量,以及定义枚举、结构体、类和协议类型。你还可以使用声明来扩展现有具名类型的行为,并将其他地方声明的符号引入到你的程序中。 -In Swift, most declarations are also definitions in the sense that they're implemented -or initialized at the same time they're declared. That said, because protocols don't -implement their members, most protocol members are declarations only. For convenience -and because the distinction isn't that important in Swift, -the term *declaration* covers both declarations and definitions. +在 Swift 中,大多数声明也是定义,因为它们在声明的同时被实现或初始化。但由于协议不实现它的成员,所以协议成员在此仅仅是声明。为了方便起见,而且这种区别在 Swift 中没那么重要,所以术语*声明*涵盖了声明和定义两种含义。 -> Grammar of a declaration: +> 声明的语法: > > *declaration* → *import-declaration* \ > *declaration* → *constant-declaration* \ @@ -41,44 +26,21 @@ the term *declaration* covers both declarations and definitions. > *declaration* → *operator-declaration* \ > *declaration* → *precedence-group-declaration* \ -## Top-Level Code - -The top-level code in a Swift source file consists of zero or more statements, -declarations, and expressions. -By default, variables, constants, and other named declarations that are declared -at the top-level of a source file are accessible to code -in every source file that's part of the same module. -You can override this default behavior -by marking the declaration with an access-level modifier, -as described in . - -There are two kinds of top-level code: -top-level declarations and executable top-level code. -Top-level declarations consist of only declarations, -and are allowed in all Swift source files. -Executable top-level code contains statements and expressions, -not just declarations, -and is allowed only as the top-level entry point for the program. - -The Swift code you compile to make an executable -can contain at most one of the following approaches -to mark the top-level entry point, -regardless of how the code is organized into files and modules: -the `main` attribute, -the `NSApplicationMain` attribute, -the `UIApplicationMain` attribute, -a `main.swift` file, -or a file that contains top-level executable code. - -> Grammar of a top-level declaration: +## 顶级代码 + +Swift 源文件中的顶级代码由零个或多个语句、声明和表达式组成。默认情况下,在源文件顶层声明的变量、常量和其他具名声明可以被同一模块中每个源文件的代码访问。你可以使用访问级别修饰符来重写此默认行为,具体说明见 。 + +有两种类型的顶级代码:顶级声明和可执行的顶级代码。顶级声明仅由声明组成,允许出现在所有 Swift 源文件中。可执行的顶级代码包含语句和表达式,而不仅仅是声明,仅允许作为程序的顶级入口点。 + +编译 Swift 代码生成可执行文件时,无论文件和模块中的代码如何组织,都只能通过以下方法之一来指定顶级入口点:`main` 特性、`NSApplicationMain` 特性、`UIApplicationMain` 特性、`main.swift` 文件,或包含顶级可执行代码的文件。 + +> 顶级声明的语法: > > *top-level-declaration* → *statements*_?_ -## Code Blocks +## 代码块 -A *code block* is used by a variety of declarations and control structures -to group statements together. -It has the following form: +*代码块*被各种声明和控制结构用来将语句组合在一起。它具有以下形式: ```swift { @@ -86,10 +48,7 @@ It has the following form: } ``` -The *statements* inside a code block include declarations, -expressions, and other kinds of statements and are executed in order -of their appearance in source code. - +代码块中的*语句*包括声明、表达式和其他类型的语句,并按它们在源代码中出现的顺序执行。 @@ -98,28 +57,19 @@ of their appearance in source code. TODO: Discuss scope. I assume a code block creates a new scope? --> -> Grammar of a code block: +> 代码块的语法: > > *code-block* → **`{`** *statements*_?_ **`}`** -## Import Declaration +## 导入声明 -An *import declaration* lets you access symbols -that are declared outside the current file. -The basic form imports the entire module; -it consists of the `import` keyword followed by a module name: +*导入声明*允许你访问在当前文件之外声明的符号。基本形式是导入整个模块;它由 `import` 关键字后跟模块名称组成。 ```swift import <#module#> ``` -Providing more detail limits which symbols are imported --- -you can specify a specific submodule -or a specific declaration within a module or submodule. -When this detailed form is used, -only the imported symbol -(and not the module that declares it) -is made available in the current scope. +提供更多细节可以限制导入哪些符号——可以指定特定的子模块,也可以指定模块或子模块中特定的声明。使用这种限制后,在当前作用域中,只有被导入的符号是可用的,而不是整个模块中的所有声明。 ```swift import <#import kind#> <#module#>.<#symbol name#> @@ -130,48 +80,27 @@ import <#module#>.<#submodule#> TODO: Need to add more to this section. --> -> Grammar of an import declaration: +> 导入声明的语法: > > *import-declaration* → *attributes*_?_ **`import`** *import-kind*_?_ *import-path* > > *import-kind* → **`typealias`** | **`struct`** | **`class`** | **`enum`** | **`protocol`** | **`let`** | **`var`** | **`func`** \ > *import-path* → *identifier* | *identifier* **`.`** *import-path* -## Constant Declaration +## 常量声明 -A *constant declaration* introduces a constant named value into your program. -Constant declarations are declared using the `let` keyword and have the following form: +*常量声明*会在你的程序中引入一个具名的常量值。常量声明使用 `let` 关键字,形式如下: ```swift let <#constant name#>: <#type#> = <#expression#> ``` -A constant declaration defines an immutable binding between the *constant name* -and the value of the initializer *expression*; -after the value of a constant is set, it can't be changed. -That said, if a constant is initialized with a class object, -the object itself can change, -but the binding between the constant name and the object it refers to can't. - -When a constant is declared at global scope, -it must be initialized with a value. -When a constant declaration occurs in the context of a function or method, -it can be initialized later, -as long as it's guaranteed to have a value set -before the first time its value is read. -If the compiler can prove that the constant's value is never read, -the constant isn't required to have a value set at all. -This analysis is called *definite initialization* --- -the compiler proves that a value is definitely set before being read. - -> Note: -> Definite initialization -> can't construct proofs that require domain knowledge, -> and its ability to track state across conditionals has a limit. -> If you can determine that constant always has a value set, -> but the compiler can't prove this is the case, -> try simplifying the code paths that set the value, -> or use a variable declaration instead. +常量声明定义了*常量名称*与构造器*表达式*的值之间的不可变绑定;一旦常量的被赋值,就无法更改。也就是说,如果常量是用类对象初始化的,对象本身可以改变,但常量名称与它所指向的对象之间的绑定不能改变。 + +当常量声明在全局作用域时,常量必须赋值。当常量声明在函数或者方法的上下文中时,可以稍后初始化,只要保证在第一次读取其值之前已为其赋值。如果编译器能够证明常量的值从未被读取,则不要求该常量必须赋值。此分析称为*确定初始化*——编译器保证一个值在读取之前值已被赋值。 + +> 注意: +> 确定初始化无法分析包含特定领域的内容,并且对条件语句中的状态跟踪能力也有限。如果你可以确定常量始终有一个值,但编译器无法证明这一点,请尝试简化设置该值的代码路径,或改用变量声明。 -When a constant declaration occurs in the context of a class or structure -declaration, it's considered a *constant property*. -Constant declarations aren't computed properties and therefore don't have getters -or setters. +当常量声明出现在类或结构体声明的上下文中时,它被视为一个*常量属性*。常量声明不是计算属性,因此没有 getter 或 setter。 -If the *constant name* of a constant declaration is a tuple pattern, -the name of each item in the tuple is bound to the corresponding value -in the initializer *expression*. +如果*常量名称*是元组形式,元组中每一项的名称都会和初始化*表达式*中对应的值进行绑定。 ```swift let (firstNumber, secondNumber) = (10, 42) @@ -200,16 +124,13 @@ let (firstNumber, secondNumber) = (10, 42) ``` --> -In this example, -`firstNumber` is a named constant for the value `10`, -and `secondNumber` is a named constant for the value `42`. -Both constants can now be used independently: +在这个例子中,`firstNumber` 是值 `10` 的具名常量,而 `secondNumber` 是值 `42` 的具名常量。现在这两个常量可以独立使用: ```swift print("The first number is \(firstNumber).") -// Prints "The first number is 10." +// 打印 "The first number is 10." print("The second number is \(secondNumber).") -// Prints "The second number is 42." +// 打印 "The second number is 42." ``` -The type annotation (`:` *type*) is optional in a constant declaration -when the type of the *constant name* can be inferred, -as described in . +在常量声明中,当可以推断出*常量名称*的类型时,类型注释(`:` *type*)是可选的,详见 。 -To declare a constant type property, -mark the declaration with the `static` declaration modifier. -A constant type property of a class is always implicitly final; -you can't mark it with the `class` or `final` declaration modifier -to allow or disallow overriding by subclasses. -Type properties are discussed in . +要声明一个常量类型属性,请使用 `static` 声明修饰符标记该声明。类的常量类型属性总是隐式为 final;你无法用 class 或 final 声明修饰符实现允许或禁止被子类重写的目的。类型属性的讨论请参见 -For more information about constants and for guidance about when to use them, -see and . +有关常量的更多信息以及何时使用它们的指导,请参见 。 -> Grammar of a constant declaration: +> 常量声明的语法 > > *constant-declaration* → *attributes*_?_ *declaration-modifiers*_?_ **`let`** *pattern-initializer-list* > @@ -261,58 +174,36 @@ see and *pattern-initializer* → *pattern* *initializer*_?_ \ > *initializer* → **`=`** *expression* -## Variable Declaration +## 变量声明 -A *variable declaration* introduces a variable named value into your program -and is declared using the `var` keyword. +*变量声明*会在你的程序中引入一个具名的变量值,并使用 `var` 关键字进行声明。 -Variable declarations have several forms that declare different kinds -of named, mutable values, -including stored and computed variables and properties, -stored variable and property observers, and static variable properties. -The appropriate form to use depends on -the scope at which the variable is declared and the kind of variable you intend to declare. +变量声明有多种形式,用于定义各种有名称的、可变的值,包括存储变量和计算变量及属性、存储变量和属性观察者,以及静态变量属性。使用哪种形式取决于变量声明的作用域以及你打算声明的变量类型。 -> Note: You can also declare properties in the context of a protocol declaration, -> as described in . +> 注意: +> 你还可以在协议声明的上下文中声明属性,参见 。 -You can override a property in a subclass by marking the subclass's property declaration -with the `override` declaration modifier, as described in . +你可以通过在子类的属性声明中标记 `override` 声明修饰符来重写属性,参见 。 -### Stored Variables and Stored Variable Properties +### 存储变量和存储变量属性 -The following form declares a stored variable or stored variable property: +以下形式声明了一个存储变量或存储变量属性: ```swift var <#variable name#>: <#type#> = <#expression#> ``` -You define this form of a variable declaration at global scope, the local scope -of a function, or in the context of a class or structure declaration. -When a variable declaration of this form is declared at global scope or the local -scope of a function, it's referred to as a *stored variable*. -When it's declared in the context of a class or structure declaration, -it's referred to as a *stored variable property*. +你可以在全局作用域、函数的局部作用域,类或结构体声明的上下文中定义这种形式的变量声明。当这种形式的变量声明在全局作用域或函数的全局作用域内声明时,它被称为*存储变量*。当它在类或结构体声明的上下文中声明时,它被称为*存储变量属性*。 -The initializer *expression* can't be present in a protocol declaration, -but in all other contexts, the initializer *expression* is optional. -That said, if no initializer *expression* is present, -the variable declaration must include an explicit type annotation (`:` *type*). +构造器*表达式*不能出现在协议声明中,但在其他场景下,构造器*表达式*是可选的。也就是说,如果没有构造器*表达式*,变量声明必须包含显式类型注释(`:` *type*)。 -As with constant declarations, -if a variable declaration omits the initializer *expression*, -the variable must have a value set before the first time it is read. -Also like constant declarations, -if the *variable name* is a tuple pattern, -the name of each item in the tuple is bound to the corresponding value -in the initializer *expression*. +与常量声明一样,如果变量声明省略了构造器*表达式*,则在第一次读取该变量之前必须为其设置一个值。同样,如果*变量名*是一个元组模式,则元组中每个项的名称都绑定到构造器*表达式*中的相应值。 -As their names suggest, the value of a stored variable or a stored variable property -is stored in memory. +如其名称所示,存储变量或存储变量属性的值存储在内存中。 -### Computed Variables and Computed Properties +### 计算变量和计算属性 -The following form declares a computed variable or computed property: +以下形式声明了一个计算变量或计算属性: ```swift var <#variable name#>: <#type#> { @@ -325,66 +216,36 @@ var <#variable name#>: <#type#> { } ``` -You define this form of a variable declaration at global scope, the local scope -of a function, or in the context of a class, structure, enumeration, or extension declaration. -When a variable declaration of this form is declared at global scope or the local -scope of a function, it's referred to as a *computed variable*. -When it's declared in the context of a class, -structure, or extension declaration, -it's referred to as a *computed property*. +你可以在全局作用域、函数的全局作用域或类、结构体、枚举或扩展声明的上下文中定义这种形式的变量声明。当这种形式的变量声明在全局作用域或函数的全局作用域内声明时,它被称为*计算变量*。当它在类、结构体或扩展声明的上下文中声明时,它被称为*计算属性*。 -The getter is used to read the value, -and the setter is used to write the value. -The setter clause is optional, -and when only a getter is needed, you can omit both clauses and simply -return the requested value directly, -as described in . -But if you provide a setter clause, you must also provide a getter clause. +getter 用于读取值,setter 用于写入值。setter 子句是可选的,当只需要 getter 时,可以省略两个子句,直接返回请求的值,参见 。但如果提供了 setter 子句,则必须同时提供 getter 子句。 -The *setter name* and enclosing parentheses is optional. -If you provide a setter name, it's used as the name of the parameter to the setter. -If you don't provide a setter name, the default parameter name to the setter is `newValue`, -as described in . +*setter 名称*和括号是可选的。如果你提供了 setter 名称,它将用作 setter 参数的名称。如果你不提供 setter 名称,setter 的默认参数名称是 `newValue`,参见 。 -Unlike stored named values and stored variable properties, -the value of a computed named value or a computed property isn't stored in memory. +与存储的具名值和存储的变量属性不同,计算的具名值或计算属性的值并不会存储在内存中。 -For more information and to see examples of computed properties, -see . +有关更多信息以及查看计算属性的示例,请参见 。 -### Stored Variable Observers and Property Observers +### 存储变量观察者和属性观察者 -You can also declare a stored variable or property with `willSet` and `didSet` observers. -A stored variable or property declared with observers has the following form: +你还可以使用 `willSet` 和 `didSet` 观察者声明一个存储变量或属性。带有观察者的存储变量或属性具有以下形式: ```swift var <#variable name#>: <#type#> = <#expression#> { - willSet(<#setter name#>) { - <#statements#> - } - didSet(<#setter name#>) { - <#statements#> - } + willSet(<#setter name#>) { + <#statements#> + } + didSet(<#setter name#>) { + <#statements#> + } } ``` -You define this form of a variable declaration at global scope, the local scope -of a function, or in the context of a class or structure declaration. -When a variable declaration of this form is declared at global scope or the local -scope of a function, the observers are referred to as *stored variable observers*. -When it's declared in the context of a class or structure declaration, -the observers are referred to as *property observers*. +你可以在全局作用域、函数的全局作用域或类或结构体声明的上下文中定义这种变量声明形式。当这种形式的变量声明在全局作用域或函数的全局作用域内声明时,观察者被称为*存储变量观察者*。当它在类或结构体声明的上下文中声明时,观察者被称为*属性观察者*。 -You can add property observers to any stored property. You can also add property -observers to any inherited property (whether stored or computed) by overriding -the property within a subclass, as described in . +你可以为任何存储属性添加属性观察者。你还可以通过在子类中重写属性,为任何继承自父类的属性(无论是存储的还是计算的)添加属性观察者,参见 。 -The initializer *expression* is optional in the context of a class or structure declaration, -but required elsewhere. The *type* annotation is optional -when the type can be inferred from the initializer *expression*. -This expression is evaluated the first time you read the property's value. -If you overwrite the property's initial value without reading it, -this expression is evaluated before the first time you write to the property. +构造器*表达式*在类或结构体声明的上下文中是可选的,但在其他地方是必须的。如果能通过构造器*表达式*推断出类型,则*类型*标注是可选的。通常,表达式的类型推断发生在首次读取属性时。如果在读取属性之前,初值已经被重写,则推断发生在首次写入属性时。 -The `willSet` and `didSet` observers provide a way to observe (and to respond appropriately) -when the value of a variable or property is being set. -The observers aren't called when the variable or property -is first initialized. -Instead, they're called only when the value is set outside of an initialization context. - -A `willSet` observer is called just before the value of the variable or property -is set. The new value is passed to the `willSet` observer as a constant, -and therefore it can't be changed in the implementation of the `willSet` clause. -The `didSet` observer is called immediately after the new value is set. In contrast -to the `willSet` observer, the old value of the variable or property -is passed to the `didSet` observer in case you still need access to it. That said, -if you assign a value to a variable or property within its own `didSet` observer clause, -that new value that you assign will replace the one that was just set and passed to -the `willSet` observer. - -The *setter name* and enclosing parentheses in the `willSet` and `didSet` clauses are optional. -If you provide setter names, -they're used as the parameter names to the `willSet` and `didSet` observers. -If you don't provide setter names, -the default parameter name to the `willSet` observer is `newValue` -and the default parameter name to the `didSet` observer is `oldValue`. - -The `didSet` clause is optional when you provide a `willSet` clause. -Likewise, the `willSet` clause is optional when you provide a `didSet` clause. - -If the body of the `didSet` observer refers to the old value, -the getter is called before the observer, -to make the old value available. -Otherwise, the new value is stored without calling the superclass's getter. -The example below shows a computed property that's defined by the superclass -and overridden by its subclasses to add an observer. +`willSet` 和 `didSet` 观察者提供了一种在变量或属性被赋值时的观察(和响应)方式。当变量或属性首次初始化时,观察者不会被调用。相反,它们仅在初始化上下文之外的情况下,值被设置时被调用。 + +`willSet` 观察者在变量或属性的值被设置之前被调用。新值作为常量传递给 `willSet` 观察者,因此新值在 `willSet` 子句的实现中无法更改。`didSet` 观察者在新值被设置后立即被调用。与 `willSet` 观察者不同,变量或属性的旧值会传递给 `didSet` 观察者,以防你仍然需要访问它。也就是说,如果你在其自己的 `didSet` 观察者子句中给变量或属性赋值,那么你赋的这个新值将替代刚刚设置并传递给 `willSet` 观察者的值。 + +*setter 名称*和 `willSet` 与 `didSet` 子句中的括号是可选的。如果提供了 setter 名称,它们将作为 `willSet` 和 `didSet` 观察者的参数名称。如果不提供 setter 名称,`willSet` 观察者的默认参数名称是 `newValue`,而 `didSet` 观察者的默认参数名称是 `oldValue`。 + +`didSet` 子句在提供 `willSet` 子句时是可选的。同样,在提供 `didSet` 子句时,`willSet` 子句也是可选的。 + +如果在 `didSet` 主体中引用了旧值,为了使旧值可用,在调用 `didSet` 之前,会先调用 getter。否则,新的值会被存储,而不调用超类的 getter。下面的示例显示了一个由超类定义并被其子类重写以添加观察者的计算属性。 ```swift class Superclass { @@ -448,8 +286,8 @@ class Superclass { } } -// This subclass doesn't refer to oldValue in its observer, so the -// superclass's getter is called only once to print the value. +// 这个子类在它的观察器中没有引用 oldValue, +// 因此,父类的 getter 方法中的打印语句只会执行一次 class New: Superclass { override var x: Int { didSet { print("New value \(x)") } @@ -457,12 +295,13 @@ class New: Superclass { } let new = New() new.x = 100 -// Prints "Setter was called" -// Prints "Getter was called" -// Prints "New value 100" +// 打印 "Setter was called" +// 打印 "Getter was called" +// 打印 "New value 100" -// This subclass refers to oldValue in its observer, so the superclass's -// getter is called once before the setter, and again to print the value. +// 这个子类在它的观察器中引用了 oldValue, +// 因此父类的 getter 在 setter 之前会被调用一次, +// 然后再次调用以打印该值。 class NewAndOld: Superclass { override var x: Int { didSet { print("Old value \(oldValue) - new value \(x)") } @@ -470,10 +309,10 @@ class NewAndOld: Superclass { } let newAndOld = NewAndOld() newAndOld.x = 200 -// Prints "Getter was called" -// Prints "Setter was called" -// Prints "Getter was called" -// Prints "Old value 12 - new value 200" +// 打印 "Getter was called" +// 打印 "Setter was called" +// 打印 "Getter was called" +// 打印 "Old value 12 - new value 200" ``` -For more information and to see an example of how to use property observers, -see . - +有关更多信息以及如何使用属性观察者的示例,请参见 -### Type Variable Properties +### 类型变量属性 -To declare a type variable property, -mark the declaration with the `static` declaration modifier. -Classes can mark type computed properties with the `class` declaration modifier instead -to allow subclasses to override the superclass’s implementation. -Type properties are discussed in . +要声明一个类型变量属性,请使用 `static` 声明修饰符标记声明。类可以使用 `class` 声明修饰符标记类型计算属性,以允许子类重写超类的实现。类型属性的讨论请参见 。 -> Grammar of a variable declaration: +> 变量声明的语法: > > *variable-declaration* → *variable-declaration-head* *pattern-initializer-list* \ > *variable-declaration* → *variable-declaration-head* *variable-name* *type-annotation* *code-block* \ @@ -579,31 +412,22 @@ Type properties are discussed in . types of those properties aren't computed/inferred. --> -## Type Alias Declaration +## 类型别名声明 -A *type alias declaration* introduces a named alias of an existing type into your program. -Type alias declarations are declared using the `typealias` keyword and have the following form: +*类型别名声明*将现有类型的具名别名引入到你的程序中。类型别名声明使用 `typealias` 关键字声明,具有以下形式: ```swift typealias <#name#> = <#existing type#> ``` -After a type alias is declared, the aliased *name* can be used -instead of the *existing type* everywhere in your program. -The *existing type* can be a named type or a compound type. -Type aliases don't create new types; -they simply allow a name to refer to an existing type. +在声明类型别名后,别名*名称*可以在程序中的任何地方替代*现有类型*使用。*现有类型*可以是具名类型或复合类型。类型别名不会创建新类型;它们只是允许一个名称引用现有类型。 -A type alias declaration can use generic parameters -to give a name to an existing generic type. The type alias -can provide concrete types for some or all of the generic parameters -of the existing type. -For example: +类型别名声明可以使用泛型参数为现有的泛型类型命名。类型别名可以为现有类型的某些或所有泛型参数提供具体类型。例如: ```swift typealias StringDictionary = Dictionary -// The following dictionaries have the same type. +// 接下来的两个字典是同一类型 var dictionary1: StringDictionary = [:] var dictionary2: Dictionary = [:] ``` @@ -620,9 +444,7 @@ var dictionary2: Dictionary = [:] ``` --> -When a type alias is declared with generic parameters, the constraints on those -parameters must match exactly the constraints on the existing type's generic parameters. -For example: +当声明一个带有泛型参数的类型别名时,这些参数的约束必须与现有类型的泛型参数的约束完全匹配。例如: ```swift typealias DictionaryOfInts = Dictionary @@ -636,14 +458,9 @@ typealias DictionaryOfInts = Dictionary ``` --> -Because the type alias and the existing type can be used interchangeably, -the type alias can't introduce additional generic constraints. +因为类型别名和现有类型可以互换使用,类型别名不能引入额外的泛型约束。 -A type alias can forward an existing type's generic parameters -by omitting all generic parameters from the declaration. -For example, -the `Diccionario` type alias declared here -has the same generic parameters and constraints as `Dictionary`. +类型别名可以通过省略声明中的所有泛型参数来转发现有类型的泛型参数。例如,这里声明的 `Diccionario` 类型别名具有与 `Dictionary` 相同的泛型参数和约束。 ```swift typealias Diccionario = Dictionary @@ -669,11 +486,7 @@ typealias Diccionario = Dictionary typealias NotProvidingTheCorrectConstraints = Dictionary typealias ProvidingMoreSpecificConstraints = Dictionary --> - -Inside a protocol declaration, -a type alias can give a shorter and more convenient name -to a type that's used frequently. -For example: +在协议声明中,类型别名可以为经常使用的类型提供一个更短和更方便的名称。例如: ```swift protocol Sequence { @@ -702,13 +515,11 @@ func sum(_ sequence: T) -> Int where T.Element == Int { ``` --> -Without this type alias, -the `sum` function would have to refer to the associated type -as `T.Iterator.Element` instead of `T.Element`. +没有这种类型别名,`sum` 函数必须将关联类型称为 `T.Iterator.Element`,而不是 `T.Element`。 -See also . +另见 。 -> Grammar of a type alias declaration: +> 类型别名声明的语法: > > *typealias-declaration* → *attributes*_?_ *access-level-modifier*_?_ **`typealias`** *typealias-name* *generic-parameter-clause*_?_ *typealias-assignment* \ > *typealias-name* → *identifier* \ @@ -722,42 +533,27 @@ See also . typealias-assignment -> ``=`` type --> -## Function Declaration +## 函数声明 -A *function declaration* introduces a function or method into your program. -A function declared in the context of class, structure, enumeration, or protocol -is referred to as a *method*. -Function declarations are declared using the `func` keyword and have the following form: +*函数声明*将一个函数或方法引入到你的程序中。在类、结构体、枚举或协议的上下文中声明的函数被称为*方法*。函数声明使用 `func` 关键字声明,具有以下形式: ```swift func <#function name#>(<#parameters#>) -> <#return type#> { - <#statements#> + <#statements#> } ``` -If the function has a return type of `Void`, -the return type can be omitted as follows: +如果函数的返回类型是 `Void` ,则可以省略返回类型,如下所示: ```swift func <#function name#>(<#parameters#>) { - <#statements#> + <#statements#> } ``` -The type of each parameter must be included --- -it can't be inferred. -If you write `inout` in front of a parameter's type, -the parameter can be modified inside the scope of the function. -In-out parameters are discussed in detail -in , below. +因为参数类型无法被推断出来,所以函数的每个参数必须明确指定类型。如果在参数类型前写上 `inout`,则该参数可以在函数的作用域内被修改。关于 in-out 参数的详细讨论请参见下面的 。 -A function declaration whose *statements* -include only a single expression -is understood to return the value of that expression. -This implicit return syntax is considered -only when the expression's type and the function's return type -aren't `Void` -and aren't an enumeration like `Never` that doesn't have any cases. +如果一个函数声明中的*语句*只包含一个表达式,则默认返回该表达式的值。只有在表达式的类型和函数的返回类型不是 `Void`,并且不是像 `Never` 那样没有任何枚举值的枚举时,才会考虑这种隐式返回语法。 -Functions can return multiple values using a tuple type -as the return type of the function. +函数可以使用元组类型作为返回类型来返回多个值。 -A function definition can appear inside another function declaration. -This kind of function is known as a *nested function*. +在函数内部,可以定义另一个函数。这种定义在函数内部的函数,被称为*嵌套函数*。 -A nested function is nonescaping if it captures -a value that's guaranteed to never escape --- -such as an in-out parameter --- -or passed as a nonescaping function argument. -Otherwise, the nested function is an escaping function. +如果一个嵌套函数捕获了一个保证不会逃逸的值——例如一个 in-out 参数——或者作为一个非逃逸函数参数传递,那么这个嵌套函数就是非逃逸的。否则,嵌套函数就是逃逸的。 -For a discussion of nested functions, -see . +有关嵌套函数的讨论,请参见 。 -### Parameter Names +### 参数名称 -Function parameters are a comma-separated list -where each parameter has one of several forms. -The order of arguments in a function call -must match the order of parameters in the function's declaration. -The simplest entry in a parameter list has the following form: +函数的参数是一个以逗号分隔的列表,每个参数都可以是不同的类型。函数调用时的参数顺序必须和函数声明时的参数顺序一致。最简单的参数列表有着如下的形式: ```swift <#parameter name#>: <#parameter type#> ``` -A parameter has a name, -which is used within the function body, -as well as an argument label, -which is used when calling the function or method. -By default, -parameter names are also used as argument labels. -For example: +参数有名称和标签,名称用于在函数内访问参数,标签用于在调用函数时指定参数。默认情况下,参数的名称也可以作为标签。例如: ```swift func f(x: Int, y: Int) -> Int { return x + y } -f(x: 1, y: 2) // both x and y are labeled +f(x: 1, y: 2) // x 和 y 都带有标签 ``` @@ -825,27 +604,20 @@ f(x: 1, y: 2) // both x and y are labeled Tracking bug is --> -You can override the default behavior for argument labels -with one of the following forms: +你可以使用以下形式(选其一),重写参数标签的默认行为: ```swift <#argument label#> <#parameter name#>: <#parameter type#> _ <#parameter name#>: <#parameter type#> ``` -A name before the parameter name -gives the parameter an explicit argument label, -which can be different from the parameter name. -The corresponding argument must use the given argument label -in function or method calls. +在参数名称前的名称会作为这个参数的显式实参标签,它可以和参数名称不同。在函数或方法调用时,相对应的参数必须使用这个实参标签。 -An underscore (`_`) before a parameter name -suppresses the argument label. -The corresponding argument must have no label in function or method calls. +参数名称前的下划线(`_`)可以去除参数的实参标签。在函数或方法调用时,相对应的参数必须去除标签。 ```swift -func repeatGreeting(_ greeting: String, count n: Int) { /* Greet n times */ } -repeatGreeting("Hello, world!", count: 2) // count is labeled, greeting is not +func repeatGreeting(_ greeting: String, count n: Int) { /* 打招呼 n 次 */ } +repeatGreeting("Hello, world!", count: 2) // count 带有标签,greeting 没有 ``` -### Parameter Modifiers +### 参数修饰符 -A *parameter modifier* changes how an argument is passed to the function. +*参数修饰符*改变了参数传递给函数的方式。 ```swift <#argument label#> <#parameter name#>: <#parameter modifier#> <#parameter type#> ``` -To use a parameter modifier, -write `inout`, `borrowing`, or `consuming` -before the argument's type. +要使用参数修饰符,请在参数类型之前写 `inout`、`borrowing` 或 `consuming`。 ```swift func someFunction(a: inout A, b: consuming B, c: C) { ... } ``` -#### In-Out Parameters - -By default, function arguments in Swift are passed by value: -Any changes made within the function are not visible in the caller. -To make an in-out parameter instead, -you apply the `inout` parameter modifier. +#### In-Out 参数 +默认情况下,Swift 中的函数参数是按值传递的:在函数内进行的任何更改对调用者都是不可见的。如果需要传入一个 in-out 参数,可以使用 `inout` 参数修饰符。 ```swift func someFunction(a: inout Int) { @@ -887,48 +653,25 @@ func someFunction(a: inout Int) { } ``` -When calling a function that includes in-out parameters, -the in-out argument must be prefixed with an ampersand (`&`) -to mark that the function call can change the argument's value. +当调用包含 in-out 参数的函数时,必须在 in-out 参数前加上 &(与符号),以表明函数调用可以更改该参数的值。 ```swift var x = 7 someFunction(&x) -print(x) // Prints "8" -``` - -In-out parameters are passed as follows: - -1. When the function is called, - the value of the argument is copied. -2. In the body of the function, - the copy is modified. -3. When the function returns, - the copy's value is assigned to the original argument. - -This behavior is known as *copy-in copy-out* -or *call by value result*. -For example, -when a computed property or a property with observers -is passed as an in-out parameter, -its getter is called as part of the function call -and its setter is called as part of the function return. - -As an optimization, -when the argument is a value stored at a physical address in memory, -the same memory location is used both inside and outside the function body. -The optimized behavior is known as *call by reference*; -it satisfies all of the requirements -of the copy-in copy-out model -while removing the overhead of copying. -Write your code using the model given by copy-in copy-out, -without depending on the call-by-reference optimization, -so that it behaves correctly with or without the optimization. - -Within a function, don't access a value that was passed as an in-out argument, -even if the original value is available in the current scope. -Accessing the original is a simultaneous access of the value, -which violates memory exclusivity. +print(x) // 打印 "8" +``` + +In-out 参数的传递方式如下: + +1. 当函数被调用时,参数的值会被复制。 +2. 在函数体内,副本被修改。 +3. 当函数返回时,副本的值被赋给原始参数。 + +这种行为被称为*拷入拷出(copy-in copy-out)* 或*值结果调用(call by value result)*。例如,当一个计算属性或一个带观察者的属性作为 in-out 参数传递时,它的 getter 在函数调用中被调用,而它的 setter 在函数返回时被调用。 + +作为一种优化手段,当参数值存储在内存中的物理地址时,在函数体内部和外部均会使用同一内存位置。这种优化行为被称为*引用调用(call by reference)*; 它满足了 copy-in copy-out 模型的所有要求,同时消除了复制的开销。请使用 copy-in copy-out 给出的模型编写代码,而不依赖于引用传递优化,以便在有或没有优化的情况下都能正确运行。 + +在函数内,不要访问作为 in-out 参数传递的值,即使原始值在当前作用域中可用。访问原始值是对该值的同时访问,这违反了内存独占性。 ```swift var someValue: Int @@ -936,12 +679,11 @@ func someFunction(a: inout Int) { a += someValue } -// Error: This causes a runtime exclusivity violation +// 错误:这会导致运行时排他性违规 someFunction(&someValue) ``` -For the same reason, -you can't pass the same value to multiple in-out parameters. +出于同样的原因,你不能将相同的值传递给多个 in-out 参数。 ```swift var someValue: Int @@ -950,12 +692,11 @@ func someFunction(a: inout Int, b: inout Int) { b += 1 } -// Error: Cannot pass the same value to multiple in-out parameters +// 错误:不能将同一个值传递给多个 in-out 参数 someFunction(&someValue, &someValue) ``` -For more information about memory safety and memory exclusivity, -see . +有关内存安全和内存独占的更多信息,请参见 -A closure or nested function -that captures an in-out parameter must be nonescaping. -If you need to capture an in-out parameter -without mutating it, -use a capture list to explicitly capture the parameter immutably. +捕获 in-out 参数的闭包或嵌套函数必须是非逃逸的。如果你需要捕获一个 in-out 参数而不对其进行修改,请使用捕获列表显式地以不可变方式捕获该参数。 ```swift func someFunction(a: inout Int) -> () -> Int { @@ -994,18 +731,15 @@ func someFunction(a: inout Int) -> () -> Int { ``` --> -If you need to capture and mutate an in-out parameter, -use an explicit local copy, -such as in multithreaded code that ensures -all mutation has finished before the function returns. +如果你需要捕获并修改一个 in-out 参数,请使用一个显式的局部副本,例如在多线程代码中,确保所有修改在函数返回之前都已完成。 ```swift func multithreadedFunction(queue: DispatchQueue, x: inout Int) { - // Make a local copy and manually copy it back. + // 创建一个本地副本,并在函数结束时手动将其复制回去。 var localX = x defer { x = localX } - // Operate on localX asynchronously, then wait before returning. + // 异步操作 localX,然后在返回之前等待。 queue.async { someMutatingOperation(&localX) } queue.sync {} } @@ -1029,8 +763,7 @@ func multithreadedFunction(queue: DispatchQueue, x: inout Int) { ``` --> -For more discussion and examples of in-out parameters, -see . +有关 in-out 参数的更多讨论和示例,请参见 .。 -#### Borrowing and Consuming Parameters +#### 借用和消费参数 -By default, Swift uses a set of rules -to automatically manage object lifetime across function calls, -copying values when required. -The default rules are designed to minimize overhead in most cases --- -if you want more specific control, -you can apply the `borrowing` or `consuming` parameter modifier. -In this case, -use `copy` to explicitly mark copy operations. +默认情况下,Swift 使用一套规则在函数调用之间自动管理对象生命周期,在需要时复制值。默认规则旨在在大多数情况下最小化开销——如果你想要更具体的控制,可以应用 `borrowing` 或 `consuming` 参数修饰符。在这种情况下,使用 `copy` 显式标记复制操作。 -Regardless of whether you use the default rules, -Swift guarantees that object lifetime and -ownership are correctly managed in all cases. -These parameter modifiers impact only the relative efficiency -of particular usage patterns, not correctness. +无论你是否使用默认规则,Swift 确保在所有情况下对象的生命周期和所有权都得到正确管理。这些参数修饰符仅影响特定使用模式的相对效率,而不影响正确性。 -The `borrowing` modifier indicates that the function -does not keep the parameter's value. -In this case, the caller maintains ownership of the object -and the responsibility for the object's lifetime. -Using `borrowing` minimizes overhead when the function -uses the object only transiently. +`borrowing` 修饰函数参数时,函数不会保留参数的值。在这种情况下,调用者保留对象的所有权,并负责对象的生命周期管理。所以当函数只是临时使用对象时,用 `borrowing` 修饰可以最大限度地减少开销。 ```swift -// `isLessThan` does not keep either argument +// `isLessThan` 不会保留任一参数 func isLessThan(lhs: borrowing A, rhs: borrowing A) -> Bool { ... } ``` -If the function needs to keep the parameter's value -for example, by storing it in a global variable --- -you use `copy` to explicitly copy that value. +如果函数需要保留参数的值,例如,通过将其存储在全局变量中——你可以使用 `copy` 显式地复制该值。 ```swift -// As above, but this `isLessThan` also wants to record the smallest value +// 同样是 `isLessThan` 函数,这个 `isLessThan` 可以将最小值记录下来 func isLessThan(lhs: borrowing A, rhs: borrowing A) -> Bool { if lhs < storedValue { storedValue = copy lhs @@ -1120,40 +835,31 @@ func isLessThan(lhs: borrowing A, rhs: borrowing A) -> Bool { } ``` -Conversely, -the `consuming` parameter modifier indicates -that the function takes ownership of the value, -accepting responsibility for either storing or destroying it -before the function returns. +相反,`consuming` 参数修饰符表示该函数拥有该值的所有权,负责在函数返回之前存储或销毁它。 ```swift -// `store` keeps its argument, so mark it `consuming` +// `store` 会保留它的参数,因此将其标记为 `consuming` func store(a: consuming A) { someGlobalVariable = a } ``` -Using `consuming` minimizes overhead when the caller no longer -needs to use the object after the function call. +使用 `consuming` 可以在调用者在函数调用后不再需要使用该对象时,最小化开销。 ```swift -// Usually, this is the last thing you do with a value +// 通常,这就是最后一次使用 value 了 store(a: value) ``` -If you keep using a copyable object after the function call, -the compiler automatically makes a copy of that object -before the function call. +如果在函数调用后继续使用可复制对象,编译器会在函数调用之前自动复制该对象。 ```swift -// The compiler inserts an implicit copy here -store(a: someValue) // This function consumes someValue -print(someValue) // This uses the copy of someValue +// 编译器会在这里插入一个隐式副本 +store(a: someValue) // 此函数消费 someValue +print(someValue) // 这里使用的是 someValue 的副本 ``` -Unlike `inout`, neither `borrowing` nor -`consuming` parameters require any special -notation when you call the function: +与 `inout` 不同,`borrowing` 和 `consuming` 参数在调用函数时不需要任何特殊标记: ```swift func someFunction(a: borrowing A, b: consuming B) { ... } @@ -1161,44 +867,35 @@ func someFunction(a: borrowing A, b: consuming B) { ... } someFunction(a: someA, b: someB) ``` -The explicit use of either `borrowing` or `consuming` -indicates your intention to more tightly control -the overhead of runtime ownership management. -Because copies can cause unexpected runtime ownership -operations, -parameters marked with either of these -modifiers cannot be copied unless you -use an explicit `copy` keyword: +显式使用 `borrowing` 或 `consuming` 表示你希望更严格地控制运行时所有权管理的开销。因为复制可能导致意外的运行时所有权操作,所以标记为这两种修饰符的参数在没有使用显式的 `copy` 关键字的情况下不能被复制: ```swift func borrowingFunction1(a: borrowing A) { - // Error: Cannot implicitly copy a - // This assignment requires a copy because - // `a` is only borrowed from the caller. + // 错误:无法隐式复制 a + // 这个赋值操作需要复制,因为 `a` 只是从调用者那里借来的。 someGlobalVariable = a } func borrowingFunction2(a: borrowing A) { - // OK: Explicit copying works + // 可以:显式复制是可以的 someGlobalVariable = copy a } func consumingFunction1(a: consuming A) { - // Error: Cannot implicitly copy a - // This assignment requires a copy because - // of the following `print` + // 错误:无法隐式复制 a + // 这个赋值操作需要复制,因为后面有 `print` someGlobalVariable = a print(a) } func consumingFunction2(a: consuming A) { - // OK: Explicit copying works regardless + // 可以:显式复制在这种情况下有效 someGlobalVariable = copy a print(a) } func consumingFunction3(a: consuming A) { - // OK: No copy needed here because this is the last use + // 可以:不需要复制,因为这是最后一次使用 someGlobalVariable = a } ``` @@ -1210,12 +907,9 @@ func consumingFunction3(a: consuming A) { TODO: Any change of parameter modifier is ABI-breaking --> -### Special Kinds of Parameters +### 特殊类型的参数 -Parameters can be ignored, -take a variable number of values, -and provide default values -using the following forms: +参数可以被忽略,数量可以不固定,还可以为其提供默认值,使用形式如下 ```swift _ : <#parameter type#> @@ -1223,30 +917,17 @@ _ : <#parameter type#> <#parameter name#>: <#parameter type#> = <#default argument value#> ``` -An underscore (`_`) parameter -is explicitly ignored and can't be accessed within the body of the function. +下划线 (`_`) 参数被显式忽略,无法在函数体内访问。 -A parameter with a base type name followed immediately by three dots (`...`) -is understood as a variadic parameter. -A parameter that immediately follows a variadic parameter -must have an argument label. -A function can have multiple variadic parameters. -A variadic parameter is treated as an array that contains elements of the base type name. -For example, the variadic parameter `Int...` is treated as `[Int]`. -For an example that uses a variadic parameter, -see . +带有基本类型名称后面紧跟三个点(`...`)的参数被理解为可变参数。紧跟在可变参数后面的参数必须有一个实参标签。一个函数可以有多个可变参数。可变参数被视为包含基本类型名称元素的数组。例如,可变参数 `Int...` 被视为 `[Int]`。有关使用可变参数的示例,请参见 。 -A parameter with an equal sign (`=`) and an expression after its type -is understood to have a default value of the given expression. -The given expression is evaluated when the function is called. -If the parameter is omitted when calling the function, -the default value is used instead. +带有等号(`=`)且在类型后跟随一个表达式的参数,表示该参数有一个默认值。这个给定的表达式会在函数调用时进行求值。如果在调用函数时省略了该参数,则会使用默认值。 ```swift func f(x: Int = 42) -> Int { return x } -f() // Valid, uses default value -f(x: 7) // Valid, uses the value provided -f(7) // Invalid, missing argument label +f() // 有效,使用默认值 +f(x: 7) // 有效,使用提供的值 +f(7) // 无效,缺少实参标签 ``` -### Special Kinds of Methods +### 特殊类型的方法 -Methods on an enumeration or a structure -that modify `self` must be marked with the `mutating` declaration modifier. +枚举或结构体的方法,如果修改了 `self`,必须标记为 `mutating` 声明修饰符。 -Methods that override a superclass method -must be marked with the `override` declaration modifier. -It's a compile-time error to override a method without the `override` modifier -or to use the `override` modifier on a method -that doesn't override a superclass method. +重写超类方法的方法必须标记为 `override` 声明修饰符。没有 `override` 修饰符而重写方法,或者在不重写超类方法的情况下使用 `override` 修饰符,都是编译时错误。 -Methods associated with a type -rather than an instance of a type -must be marked with the `static` declaration modifier for enumerations and structures, -or with either the `static` or `class` declaration modifier for classes. -A class type method marked with the `class` declaration modifier -can be overridden by a subclass implementation; -a class type method marked with `class final` or `static` can't be overridden. +与类型相关的方法,而不是与类型实例相关的方法,必须使用 `static` 声明修饰符来标记(枚举和结构体使用 `static`,类可以使用 `static` 或 `class` 声明修饰符)。用 `class` 声明修饰符标记的类类型方法可以被子类的实现重写;用 `class final` 或 `static` 标记的类类型方法则不能被重写。 -### Methods with Special Names +### 特殊名称的方法 -Several methods that have special names -enable syntactic sugar for function call syntax. -If a type defines one of these methods, -instances of the type can be used in function call syntax. -The function call is understood to be a call to -one of the specially named methods on that instance. +一些具有特殊名称的方法为函数调用语法提供了语法糖。如果一个类型定义了这些方法之一,该类型的实例就可以使用函数调用语法。此时的函数调用会被理解为对该实例上某个特殊命名方法的调用 -A class, structure, or enumeration type -can support function call syntax -by defining a `dynamicallyCall(withArguments:)` method -or a `dynamicallyCall(withKeywordArguments:)` method, -as described in , -or by defining a call-as-function method, as described below. -If the type defines -both a call-as-function method -and one of the methods used by the `dynamicCallable` attribute, -the compiler gives preference to the call-as-function method -in circumstances where either method could be used. +类、结构体或枚举类型可以通过定义一个 `dynamicallyCall(withArguments:)` 方法或一个 `dynamicallyCall(withKeywordArguments:)` 方法来支持函数调用语法,参见 ,或者通过定义一个作为函数调用(call-as-function)的方法,如下所述。如果该类型同时定义了一个作为函数调用的方法和 `dynamicCallable` 特性使用的其中一个方法,则在可以使用任一方法的情况下,编译器优先选择作为函数调用的方法。 -The name of a call-as-function method is `callAsFunction()`, -or another name that begins with `callAsFunction(` -and adds labeled or unlabeled arguments --- -for example, `callAsFunction(_:_:)` and `callAsFunction(something:)` -are also valid call-as-function method names. +作为函数调用方法的名称为 `callAsFunction()`,或其他以 `callAsFunction(` 开头并带有有标签或无标签参数的名称——例如,`callAsFunction(_:_:)` 和 `callAsFunction(something:)` 也是有效的作为函数调用方法名称。 -The following function calls are equivalent: +以下函数调用是等效的: ```swift struct CallableStruct { @@ -1391,7 +1042,7 @@ struct CallableStruct { let callable = CallableStruct(value: 100) callable(4, scale: 2) callable.callAsFunction(4, scale: 2) -// Both function calls print 208. +// 两个函数调用都打印 208。 ``` -The call-as-function methods -and the methods from the `dynamicCallable` attribute -make different trade-offs between -how much information you encode into the type system -and how much dynamic behavior is possible at runtime. -When you declare a call-as-function method, -you specify the number of arguments, -and each argument's type and label. -The `dynamicCallable` attribute's methods specify only the type -used to hold the array of arguments. +作为函数调用的方法和来自 `dynamicCallable` 特性的方法在将多少信息编码到类型系统与在运行时可能的动态行为之间做出了不同的权衡。当你声明一个作为函数调用的方法时,你需要指定参数的数量,以及每个参数的类型和标签。`dynamicCallable` 特性的方法仅指定用于保存参数数组的类型。 -Defining a call-as-function method, -or a method from the `dynamicCallable` attribute, -doesn't let you use an instance of that type -as if it were a function in any context other than a function call expression. -For example: +定义一个作为函数调用的方法,或者来自 `dynamicCallable` 特性的方法,并不允许你在函数调用表达式以外的任何上下文中将该类型的实例用作函数。例如: ```swift -let someFunction1: (Int, Int) -> Void = callable(_:scale:) // Error +let someFunction1: (Int, Int) -> Void = callable(_:scale:) // 错误 let someFunction2: (Int, Int) -> Void = callable.callAsFunction(_:scale:) ``` @@ -1454,60 +1092,37 @@ let someFunction2: (Int, Int) -> Void = callable.callAsFunction(_:scale:) ``` --> -The `subscript(dynamicMember:)` subscript -enables syntactic sugar for member lookup, -as described in . +`subscript(dynamicMember:)` 下标为成员查找提供了语法糖,参见 。 -### Throwing Functions and Methods +### 抛出函数和方法 -Functions and methods that can throw an error must be marked with the `throws` keyword. -These functions and methods are known as *throwing functions* -and *throwing methods*. -They have the following form: +可以抛出错误的函数和方法必须标记 `throws` 关键字。这些函数和方法被称为*抛出函数*和*抛出方法*。它们具有以下形式: ```swift func <#function name#>(<#parameters#>) throws -> <#return type#> { - <#statements#> + <#statements#> } ``` -A function that throws a specific error type has the following form: +抛出特定错误类型的函数具有以下形式: ```swift func <#function name#>(<#parameters#>) throws(<#error type#>) -> <#return type#> { - <#statements#> + <#statements#> } ``` -Calls to a throwing function or method must be wrapped in a `try` or `try!` expression -(that is, in the scope of a `try` or `try!` operator). +调用抛出函数或方法的必须被包裹在一个 `try` 或 `try!` 表达式中(即,在 `try` 或 `try!` 操作符的作用域内)。 -A function's type includes whether it can throw an error -and what type of error it throws. -This subtype relationship means, for example, you can use a nonthrowing function -in a context where a throwing one is expected. -For more information about the type of a throwing function, -see . -For examples of working with errors that have explicit types, -see . +函数的类型包括:它是否会抛出错误,以及它抛出的错误类型。非抛出函数是抛出函数的子类型。所以,可以在使用抛出函数的地方使用非抛出函数。有关抛出错误函数类型的更多信息,请参阅 。有关处理具有显式类型的错误的示例,请参阅 。 -You can't overload a function based only on whether the function can throw an error. -That said, -you can overload a function based on whether a function *parameter* can throw an error. +你不能仅根据函数是否会抛出错误来重载一个函数。不过,你可以根据函数的*参数*是否会抛出错误来重载函数。 -A throwing method can't override a nonthrowing method, -and a throwing method can't satisfy a protocol requirement for a nonthrowing method. -That said, a nonthrowing method can override a throwing method, -and a nonthrowing method can satisfy a protocol requirement for a throwing method. +抛出方法不能重写非抛出方法,且抛出方法也不能满足协议中对非抛出方法的要求。不过,非抛出方法可以重写抛出方法,且非抛出方法也可以满足协议中对会抛出方法的要求。 -### Rethrowing Functions and Methods +### 再抛出函数和方法 -A function or method can be declared with the `rethrows` keyword -to indicate that it throws an error only if one of its function parameters throws an error. -These functions and methods are known as *rethrowing functions* -and *rethrowing methods*. -Rethrowing functions and methods -must have at least one throwing function parameter. +函数或方法可以使用 `rethrows` 关键字声明,表示它只在其某个函数参数抛出错误时才会抛出错误。这样的函数和方法被称为*再抛出函数(rethrowing functions)*和*再抛出方法(rethrowing methods)*。再抛出函数和方法必须至少有一个会抛出错误的函数参数。 ```swift func someFunction(callback: () throws -> Void) rethrows { @@ -1525,17 +1140,7 @@ func someFunction(callback: () throws -> Void) rethrows { ``` --> -A rethrowing function or method can contain a `throw` statement -only inside a `catch` clause. -This lets you call the throwing function inside a `do`-`catch` statement -and handle errors in the `catch` clause by throwing a different error. -In addition, -the `catch` clause must handle -only errors thrown by one of the rethrowing function's -throwing parameters. -For example, the following is invalid -because the `catch` clause would handle -the error thrown by `alwaysThrows()`. +再抛出的函数或方法只能在 `catch` 子句中包含 `throw` 语句。这使得你可以在 `do`-`catch` 语句中调用抛出函数,并通过抛出不同的错误在 `catch` 子句中处理错误。此外,`catch` 子句必须仅处理由再抛出函数的抛出参数抛出的错误。例如,以下是无效的,因为 `catch` 子句将处理由 `alwaysThrows()` 抛出的错误。 ```swift func alwaysThrows() throws { @@ -1544,7 +1149,7 @@ func alwaysThrows() throws { func someFunction(callback: () throws -> Void) rethrows { do { try callback() - try alwaysThrows() // Invalid, alwaysThrows() isn't a throwing parameter + try alwaysThrows() // 无效,alwaysThrows() 不是一个抛出参数 } catch { throw AnotherError.error } @@ -1595,13 +1200,9 @@ func someFunction(callback: () throws -> Void) rethrows { ``` --> -A throwing method can't override a rethrowing method, -and a throwing method can't satisfy a protocol requirement for a rethrowing method. -That said, a rethrowing method can override a throwing method, -and a rethrowing method can satisfy a protocol requirement for a throwing method. +抛出方法不能重写再抛出方法,抛出方法也不能满足再抛出方法的协议要求。也就是说,再抛出方法可以重写抛出方法,再抛出方法可以满足抛出方法的协议要求。 -An alternative to rethrowing is throwing a specific error type in generic code. -For example: +在泛型代码中,抛出特定错误类型是再抛出的替代方案。例如: ```swift func someFunction(callback: () throws(E) -> Void) throws(E) { @@ -1609,11 +1210,7 @@ func someFunction(callback: () throws(E) -> Void) throws(E) { } ``` -This approach to propagating an error -preserves type information about the error. -However, unlike marking a function `rethrows`, -this approach doesn't prevent the function -from throwing an error of the same type. +这种传播错误的方法保留了错误的类型信息。然而,与标记一个函数 `rethrows` 不同,这种方法并不阻止该函数抛出相同类型的错误。 -### Asynchronous Functions and Methods +### 异步函数和方法 -Functions and methods that run asynchronously must be marked with the `async` keyword. -These functions and methods are known as *asynchronous functions* -and *asynchronous methods*. -They have the following form: +以异步方式运行的函数和方法必须使用 `async` 关键字标记。这类函数和方法被称为*异步函数*和*异步方法*。它们的形式如下: ```swift func <#function name#>(<#parameters#>) async -> <#return type#> { - <#statements#> + <#statements#> } ``` -Calls to an asynchronous function or method -must be wrapped in an `await` expression --- -that is, they must be in the scope of an `await` operator. +对异步函数或方法的调用必须包装在一个 `await` 表达式中——也就是说,它们必须在 `await` 操作符的作用域内。 -The `async` keyword is part of the function's type, -and synchronous functions are subtypes of asynchronous functions. -As a result, you can use a synchronous function -in a context where an asynchronous function is expected. -For example, -you can override an asynchronous method with a synchronous method, -and a synchronous method can satisfy a protocol requirement -that requires an asynchronous method. +`async` 关键字是函数类型的一部分,且同步函数是异步函数的子类型。因此,你可以在需要异步函数的上下文中使用同步函数。例如,你可以用同步方法重写异步方法,且同步方法可以满足对异步方法的协议要求。 -You can overload a function based on whether or not the function is asynchronous. -At the call site, context determines which overload is used: -In an asynchronous context, the asynchronous function is used, -and in a synchronous context, the synchronous function is used. +你可以根据函数是否为异步来重载一个函数。在调用时,由上下文决定使用哪个重载:在异步上下文中,会使用异步函数,而在同步上下文中,会使用同步函数。 -An asynchronous method can't override a synchronous method, -and an asynchronous method can't satisfy a protocol requirement for a synchronous method. -That said, a synchronous method can override an asynchronous method, -and a synchronous method can satisfy a protocol requirement for an asynchronous method. +异步方法不能重写同步方法,且异步方法不能满足对同步方法的协议要求。不过,同步方法可以重写异步方法,且同步方法可以满足对异步方法的协议要求。 -### Functions that Never Return +### 永不返回的函数 -Swift defines a [`Never`][] type, -which indicates that a function or method doesn't return to its caller. -Functions and methods with the `Never` return type are called *nonreturning*. -Nonreturning functions and methods either cause an irrecoverable error -or begin a sequence of work that continues indefinitely. -This means that -code that would otherwise run immediately after the call is never executed. -Throwing and rethrowing functions can transfer program control -to an appropriate `catch` block, even when they're nonreturning. +Swift 定义了一个 [`Never`][] 类型,表示一个函数或方法不会返回给调用者。返回类型为 `Never` 的函数和方法被称为*非返回*。非返回的函数和方法要么导致不可恢复的错误,要么开始一个无限进行的工作序列。这意味着在调用后立即运行的代码永远不会被执行。即使抛出错误的函数和再抛出错误的函数是非返回类型,它们仍然可以将程序控制权转移到相应的 `catch` 块。 [`Never`]: https://developer.apple.com/documentation/swift/never -A nonreturning function or method can be called to conclude the `else` clause -of a guard statement, -as discussed in . +非返回的函数或方法可以在 guard 语句的 `else` 分支中调用,以结束该分支,见 。 -You can override a nonreturning method, -but the new method must preserve its return type and nonreturning behavior. +你可以重写一个非返回的方法,但新方法必须保持其返回类型和非返回的行为。 -> Grammar of a function declaration: +> 函数声明的语法: > > *function-declaration* → *function-head* *function-name* *generic-parameter-clause*_?_ *function-signature* *generic-where-clause*_?_ *function-body*_?_ > @@ -1726,41 +1294,23 @@ but the new method must preserve its return type and nonreturning behavior. Let's just deal with this difference in prose. --> -## Enumeration Declaration +## 枚举声明 -An *enumeration declaration* introduces a named enumeration type into your program. +*枚举声明*将一个具名的枚举类型引入到你的程序中。 -Enumeration declarations have two basic forms and are declared using the `enum` keyword. -The body of an enumeration declared using either form contains -zero or more values --- called *enumeration cases* --- -and any number of declarations, -including computed properties, -instance methods, type methods, initializers, type aliases, -and even other enumeration, structure, class, and actor declarations. -Enumeration declarations can't contain deinitializer or protocol declarations. +枚举声明有两种基本形式,使用 `enum` 关键字进行声明。使用任一形式声明的枚举的主体包含零个或多个值——称为*枚举用例*——以及任意数量的声明,包括计算属性、实例方法、类型方法、构造器、类型别名,甚至其他枚举、结构体、类和 actor 声明。枚举声明不能包含析构器或协议声明。 -Enumeration types can adopt any number of protocols, but can’t inherit from classes, -structures, or other enumerations. +枚举类型可以采用任意数量的协议,但不能从类、结构体或其他枚举继承。 -Unlike classes and structures, -enumeration types don't have an implicitly provided default initializer; -all initializers must be declared explicitly. Initializers can delegate -to other initializers in the enumeration, but the initialization process is complete -only after an initializer assigns one of the enumeration cases to `self`. +与类和结构体不同,枚举类型没有隐式提供的默认构造器;所有构造器必须显式声明。构造器可以委托给枚举中的其他构造器,但初始化过程只有在构造器将枚举的一个用例赋值给 `self` 后才完成。 -Like structures but unlike classes, enumerations are value types; -instances of an enumeration are copied when assigned to -variables or constants, or when passed as arguments to a function call. -For information about value types, -see . +像结构体但不同于类,枚举是值类型;当枚举的实例被赋值给变量或常量,或作为参数传递给函数调用时,会被复制。有关值类型的信息,请参见 。 -You can extend the behavior of an enumeration type with an extension declaration, -as discussed in . +你可以通过扩展声明扩展枚举类型的行为,如 中所讨论的。 -### Enumerations with Cases of Any Type +### 任意类型的枚举成员 -The following form declares an enumeration type that contains -enumeration cases of any type: +如下的形式声明了一个包含任意类型枚举用例的枚举变量: ```swift enum <#enumeration name#>: <#adopted protocols#> { @@ -1769,20 +1319,11 @@ enum <#enumeration name#>: <#adopted protocols#> { } ``` -Enumerations declared in this form are sometimes called *discriminated unions* -in other programming languages. +这种形式的枚举声明在其他语言中有时被叫做*可识别联合*。 -In this form, each case block consists of the `case` keyword -followed by one or more enumeration cases, separated by commas. -The name of each case must be unique. -Each case can also specify that it stores values of a given type. -These types are specified in the *associated value types* tuple, -immediately following the name of the case. +在这种形式中,每个用例块由 `case` 关键字开始,后面跟着一个或多个枚举用例,用逗号分隔。每个用例的名称必须是唯一的。每个用例还可以指定它存储特定类型的值。这些类型在*关联值类型*元组中指定,紧接在用例名称之后。 -Enumeration cases that store associated values can be used as functions -that create instances of the enumeration with the specified associated values. -And just like functions, -you can get a reference to an enumeration case and apply it later in your code. +存储关联值的枚举成员可以用作函数,这些函数创建具有指定关联值的枚举实例。就像函数一样,你可以获取对枚举成员的引用,并在代码中稍后应用它。 ```swift enum Number { @@ -1790,9 +1331,9 @@ enum Number { case real(Double) } let f = Number.integer -// f is a function of type (Int) -> Number +// f 是一个 (Int) -> Number 的函数类型 -// Apply f to create an array of Number instances with integer values +// 应用函数 `f` 来创建一个包含整数值的 `Number` 实例数组 let evenInts: [Number] = [0, 2, 4, 6].map(f) ``` @@ -1819,22 +1360,13 @@ let evenInts: [Number] = [0, 2, 4, 6].map(f) and assert() would require Number to conform to Equatable. --> -For more information and to see examples of cases with associated value types, -see . +有关更多信息以及查看枚举关联值的示例,请参见 。 -#### Enumerations with Indirection +#### 间接枚举 -Enumerations can have a recursive structure, -that is, they can have cases with associated values -that are instances of the enumeration type itself. -However, instances of enumeration types have value semantics, -which means they have a fixed layout in memory. -To support recursion, -the compiler must insert a layer of indirection. +枚举类型可以具有递归结构,就是说,枚举用例的关联值类型可以是枚举类型自身。然而,枚举类型的实例具有值语义,这意味着它们在内存中有固定布局。为了支持递归,编译器必须插入一个间接层。 -To enable indirection for a particular enumeration case, -mark it with the `indirect` declaration modifier. -An indirect case must have an associated value. +要让某个枚举用例支持递归,请使用 `indirect` 声明修饰符进行标记。间接枚举成员必须具有关联值。 -To enable indirection for all the cases of an enumeration -that have an associated value, -mark the entire enumeration with the `indirect` modifier --- -this is convenient when the enumeration contains many cases -that would each need to be marked with the `indirect` modifier. +要让一个枚举类型的所有用例都支持递归,请使用 `indirect` 修饰符标记整个枚举——当枚举包含许多需要标记为 `indirect` 修饰符的用例时,这样做非常方便。 -An enumeration that's marked with the `indirect` modifier -can contain a mixture of cases that have associated values and cases those that don't. -That said, -it can't contain any cases that are also marked with the `indirect` modifier. +使用 `indirect` 修饰符标记的枚举类型可以既包含有关联值的用例,同时还可包含没有关联值的用例。但是,它不能再单独使用 `indirect` 修饰符来标记某个用例。 -### Enumerations with Cases of a Raw-Value Type +### 带有原始值类型的枚举 -The following form declares an enumeration type that contains -enumeration cases of the same basic type: +以下形式声明了一个枚举类型,其中包含相同基本类型的枚举成员: ```swift enum <#enumeration name#>: <#raw-value type#>, <#adopted protocols#> { @@ -1916,32 +1440,14 @@ enum <#enumeration name#>: <#raw-value type#>, <#adopted protocols#> { } ``` -In this form, each case block consists of the `case` keyword, -followed by one or more enumeration cases, separated by commas. -Unlike the cases in the first form, each case has an underlying -value, called a *raw value*, of the same basic type. -The type of these values is specified in the *raw-value type* and must represent an -integer, floating-point number, string, or single character. -In particular, the *raw-value type* must conform to the `Equatable` protocol -and one of the following protocols: -`ExpressibleByIntegerLiteral` for integer literals, -`ExpressibleByFloatLiteral` for floating-point literals, -`ExpressibleByStringLiteral` for string literals that contain any number of characters, -and `ExpressibleByUnicodeScalarLiteral` -or `ExpressibleByExtendedGraphemeClusterLiteral` for string literals -that contain only a single character. -Each case must have a unique name and be assigned a unique raw value. +在这种形式中,每个用例块由 `case` 关键字开始,后面跟着一个或多个枚举用例,用逗号分隔。与第一种形式中的用例不同,每个用例都有一个基础值,称为*原始值*,其基本类型相同。这些值的类型在*原始值类型*中指定,必须表示整数、浮点数、字符串或单个字符。特别是,*原始值类型*必须遵循 `Equatable` 协议,并且遵循以下协议之一:`ExpressibleByIntegerLiteral` 用于整型字面量,`ExpressibleByFloatLiteral` 用于浮点型字面量,`ExpressibleByStringLiteral` 用于包含任意数量字符的字符串字面量,以及 `ExpressibleByUnicodeScalarLiteral` 或 `ExpressibleByExtendedGraphemeClusterLiteral` 用于仅包含单个字符的字符串字面量。每一个用例的名字和原始值必须唯一。 -If the raw-value type is specified as `Int` -and you don't assign a value to the cases explicitly, -they're implicitly assigned the values `0`, `1`, `2`, and so on. -Each unassigned case of type `Int` is implicitly assigned a raw value -that's automatically incremented from the raw value of the previous case. +如果原始值类型被指定为 `Int`,并且你没有显式地为这些用例分配值,它们将隐式地被分配值 `0`、`1`、`2`,依此类推。每个未分配的 `Int` 类型的用例将隐式地被分配一个原始值,该值是从前一个用例的原始值自动递增的。 ```swift enum ExampleEnum: Int { @@ -1959,14 +1465,9 @@ enum ExampleEnum: Int { ``` --> -In the above example, the raw value of `ExampleEnum.a` is `0` and the value of -`ExampleEnum.b` is `1`. And because the value of `ExampleEnum.c` is -explicitly set to `5`, the value of `ExampleEnum.d` is automatically incremented -from `5` and is therefore `6`. +在上述示例中,`ExampleEnum.a` 的原始值为 `0`,而 `ExampleEnum.b` 的值为 `1`。由于 `ExampleEnum.c` 的值被显式设置为 `5`,因此 `ExampleEnum.d` 的值自动从 `5` 增加,结果为 `6`。 -If the raw-value type is specified as `String` -and you don't assign values to the cases explicitly, -each unassigned case is implicitly assigned a string with the same text as the name of that case. +如果原始值类型被指定为 `String`,并且你没有显式地为各个用例分配值,则每个未分配的用例会隐式地分配一个与该成员名称相同文本的字符串。 ```swift enum GamePlayMode: String { @@ -1984,35 +1485,15 @@ enum GamePlayMode: String { ``` --> -In the above example, the raw value of `GamePlayMode.cooperative` is `"cooperative"`, -the raw value of `GamePlayMode.individual` is `"individual"`, -and the raw value of `GamePlayMode.competitive` is `"competitive"`. +在上述示例中,`GamePlayMode.cooperative` 的原始值是 `"cooperative"`,`GamePlayMode.individual` 的原始值是 `"individual"`,而 `GamePlayMode.competitive` 的原始值是 `"competitive"`。 -Enumerations that have cases of a raw-value type implicitly conform to the -`RawRepresentable` protocol, defined in the Swift standard library. -As a result, they have a `rawValue` property -and a failable initializer with the signature `init?(rawValue: RawValue)`. -You can use the `rawValue` property to access the raw value of an enumeration case, -as in `ExampleEnum.b.rawValue`. -You can also use a raw value to find a corresponding case, if there is one, -by calling the enumeration's failable initializer, -as in `ExampleEnum(rawValue: 5)`, which returns an optional case. -For more information and to see examples of cases with raw-value types, -see . +具有原始值类型的枚举隐式遵循在 Swift 标准库中定义的 `RawRepresentable` 协议。因此,它们具有 `rawValue` 属性和一个可失败构造器,其签名为 `init?(rawValue: RawValue)`。你可以使用 `rawValue` 属性访问枚举用例的原始值,如 `ExampleEnum.b.rawValue`。你还可以使用原始值通过调用枚举的可失败构造器来查找相应的用例,如 `ExampleEnum(rawValue: 5)`,这将返回一个可选的用例。有关更多信息以及查看具有原始值类型的案例示例,请参见 。 -### Accessing Enumeration Cases +### 访问枚举成员 -To reference the case of an enumeration type, use dot (`.`) syntax, -as in `EnumerationType.enumerationCase`. When the enumeration type can be inferred -from context, you can omit it (the dot is still required), -as described in -and . +要引用枚举类型的用例,请使用点(`.`)语法,如 `EnumerationType.enumerationCase` 所示。当枚举类型可以从上下文中推断时,可以省略它(仍然需要 `.`),参见 。 -To check the values of enumeration cases, use a `switch` statement, -as shown in . -The enumeration type is pattern-matched against the enumeration case patterns -in the case blocks of the `switch` statement, -as described in . +要检查枚举用例的值,请使用 `switch` 语句,如 中所示。在 `switch` 语句的用例分支中,枚举类型会与枚举用例进行模式匹配,详见 -> Grammar of an enumeration declaration: +> 枚举声明的语法: > > *enum-declaration* → *attributes*_?_ *access-level-modifier*_?_ *union-style-enum* \ > *enum-declaration* → *attributes*_?_ *access-level-modifier*_?_ *raw-value-style-enum* @@ -2074,56 +1555,35 @@ as described in . and they behave differently. --> -## Structure Declaration +## 结构体声明 -A *structure declaration* introduces a named structure type into your program. -Structure declarations are declared using the `struct` keyword and have the following form: +*结构体声明*将一个具名的结构体类型引入到你的程序中。结构体声明使用 `struct` 关键字声明,具有以下形式: ```swift struct <#structure name#>: <#adopted protocols#> { - <#declarations#> + <#declarations#> } ``` -The body of a structure contains zero or more *declarations*. -These *declarations* can include both stored and computed properties, -type properties, instance methods, type methods, initializers, subscripts, -type aliases, and even other structure, class, actor, and enumeration declarations. -Structure declarations can't contain deinitializer or protocol declarations. -For a discussion and several examples of structures -that include various kinds of declarations, -see . +结构体的主体包含零个或多个*声明*。这些*声明*可以包括存储属性和计算属性、类型属性、实例方法、类型方法、构造器、下标、类型别名,甚至其他结构体、类、actor 和枚举声明。结构体声明不能包含析构器或协议声明。有关包含各种类型声明的结构体的讨论和多个示例,请参见 。 -Structure types can adopt any number of protocols, -but can't inherit from classes, enumerations, or other structures. +结构体类型可以采用任意数量的协议,但不能从类、枚举或其他结构体继承。 -There are three ways to create an instance of a previously declared structure: +有三种方法可以创建先前声明的结构体的实例: -- Call one of the initializers declared within the structure, - as described in . -- If no initializers are declared, - call the structure's memberwise initializer, - as described in . -- If no initializers are declared, - and all properties of the structure declaration were given initial values, - call the structure's default initializer, - as described in . +- 调用结构体中声明的某个构造器,参见 。 +- 如果没有声明构造器,则调用结构体的成员遍历构造器,参见 。 +- 如果没有声明构造器,且结构体声明的所有属性都给定了初始值,则调用结构体的默认构造器,参见 。 -The process of initializing a structure's declared properties -is described in . +初始化结构体中声明属性的过程在 中描述。 -Properties of a structure instance can be accessed using dot (`.`) syntax, -as described in . +结构体实例的属性可以使用点 (`.`) 语法访问,参见 。 -Structures are value types; instances of a structure are copied when assigned to -variables or constants, or when passed as arguments to a function call. -For information about value types, -see . +结构体是值类型;当结构体的实例被赋值给变量或常量,或作为参数传递给函数调用时,会被复制。有关值类型的信息,请参见 。 -You can extend the behavior of a structure type with an extension declaration, -as discussed in . +你可以通过扩展声明来扩展结构体类型的行为,参见 。 -> Grammar of a structure declaration: +> 结构体声明的语法: > > *struct-declaration* → *attributes*_?_ *access-level-modifier*_?_ **`struct`** *struct-name* *generic-parameter-clause*_?_ *type-inheritance-clause*_?_ *generic-where-clause*_?_ *struct-body* \ > *struct-name* → *identifier* \ @@ -2132,46 +1592,23 @@ as discussed in . > *struct-members* → *struct-member* *struct-members*_?_ \ > *struct-member* → *declaration* | *compiler-control-statement* -## Class Declaration +## 类声明 -A *class declaration* introduces a named class type into your program. -Class declarations are declared using the `class` keyword and have the following form: +*类声明*将一个具名的类类型引入到你的程序中。类声明使用 `class` 关键字声明,具有以下形式: ```swift class <#class name#>: <#superclass#>, <#adopted protocols#> { - <#declarations#> + <#declarations#> } ``` -The body of a class contains zero or more *declarations*. -These *declarations* can include both stored and computed properties, -instance methods, type methods, initializers, -a single deinitializer, subscripts, type aliases, -and even other class, structure, actor, and enumeration declarations. -Class declarations can't contain protocol declarations. -For a discussion and several examples of classes -that include various kinds of declarations, -see . +类的主体包含零个或多个*声明*。这些*声明*可以包括存储属性和计算属性、实例方法、类型方法、构造器、一个析构器、下标、类型别名,甚至其他类、结构体、actor 和枚举声明。类声明不能包含协议声明。有关包含各种类型声明的类的讨论和多个示例,请参见 。 -A class type can inherit from only one parent class, its *superclass*, -but can adopt any number of protocols. -The *superclass* appears first after the *class name* and colon, -followed by any *adopted protocols*. -Generic classes can inherit from other generic and nongeneric classes, -but a nongeneric class can inherit only from other nongeneric classes. -When you write the name of a generic superclass class after the colon, -you must include the full name of that generic class, -including its generic parameter clause. +类类型只能继承自一个父类,即它的*超类*,但可以采用任意数量的协议。*超类*在*类名*和冒号之后首先出现,后面跟着任何*采用的协议*。泛型类可以继承其他泛型和非泛型类,但非泛型类只能继承其他非泛型类。当你在冒号后写泛型超类的名称时,必须包括该泛型类的全名,包括其泛型参数子句。 -As discussed in , -classes can have designated and convenience initializers. -The designated initializer of a class must initialize all of the class's -declared properties and it must do so before calling any of its superclass's -designated initializers. +如在 中讨论的,类可以有指定构造器和便利构造器。类的指定构造器必须初始化所有声明的属性,并且必须在调用任何超类的指定构造器之前完成此操作。 -A class can override properties, methods, subscripts, and initializers of its superclass. -Overridden properties, methods, subscripts, -and designated initializers must be marked with the `override` declaration modifier. +类可以重写其超类的属性、方法、下标和构造器。重写的属性、方法、下标和指定构造器必须标记为 `override` 声明修饰符。 -To require that subclasses implement a superclass's initializer, -mark the superclass's initializer with the `required` declaration modifier. -The subclass's implementation of that initializer -must also be marked with the `required` declaration modifier. +要要求子类实现超类的构造器,请使用 `required` 声明修饰符标记超类的构造器。子类对该构造器的实现也必须使用 `required` 声明修饰符进行标记。 -Although properties and methods declared in the *superclass* are inherited by -the current class, designated initializers declared in the *superclass* are only -inherited when the subclass meets the conditions described in -. -Swift classes don't inherit from a universal base class. +尽管在*超类*中声明的属性和方法被当前类继承,但在*超类*中声明的指定构造器仅在子类满足 中描述的条件时才会被继承。Swift 类不从通用基类继承。 -There are two ways to create an instance of a previously declared class: +有两种方法可以创建一个先前声明的类的实例: -- Call one of the initializers declared within the class, - as described in . -- If no initializers are declared, - and all properties of the class declaration were given initial values, - call the class's default initializer, - as described in . +- 调用类中声明的某个构造器,参见 。 +- 如果没有声明构造器,且类声明的所有属性都给定了初始值,则调用类的默认构造器,参见 。 -Access properties of a class instance with dot (`.`) syntax, -as described in . +使用点(`.`)语法访问类实例的属性,参见 。 -Classes are reference types; instances of a class are referred to, rather than copied, -when assigned to variables or constants, or when passed as arguments to a function call. -For information about reference types, -see . +类是引用类型;当类的实例被赋值给变量或常量,或作为参数传递给函数调用时,是引用而不是复制。有关引用类型的信息,请参见 。 -You can extend the behavior of a class type with an extension declaration, -as discussed in . +你可以通过扩展声明扩展类类型的行为,参见 。 -> Grammar of a class declaration: +> 类声明的语法: > > *class-declaration* → *attributes*_?_ *access-level-modifier*_?_ **`final`**_?_ **`class`** *class-name* *generic-parameter-clause*_?_ *type-inheritance-clause*_?_ *generic-where-clause*_?_ *class-body* \ > *class-declaration* → *attributes*_?_ **`final`** *access-level-modifier*_?_ **`class`** *class-name* *generic-parameter-clause*_?_ *type-inheritance-clause*_?_ *generic-where-clause*_?_ *class-body* \ @@ -2223,10 +1644,9 @@ as discussed in . > *class-members* → *class-member* *class-members*_?_ \ > *class-member* → *declaration* | *compiler-control-statement* -## Actor Declaration +## Actor 声明 -An *actor declaration* introduces a named actor type into your program. -Actor declarations are declared using the `actor` keyword and have the following form: +*actor 声明*将一个具名的 actor 类型引入到你的程序中。actor 声明使用 `actor` 关键字声明,具有以下形式: ```swift actor <#actor name#>: <#adopted protocols#> { @@ -2234,64 +1654,28 @@ actor <#actor name#>: <#adopted protocols#> { } ``` -The body of an actor contains zero or more *declarations*. -These *declarations* can include both stored and computed properties, -instance methods, type methods, initializers, -a single deinitializer, subscripts, type aliases, -and even other class, structure, and enumeration declarations. -For a discussion and several examples of actors -that include various kinds of declarations, -see . +actor 的主体包含零个或多个*声明*。这些*声明*可以包括存储属性和计算属性、实例方法、类型方法、构造器、一个析构器、下标、类型别名,甚至其他类、结构体和枚举声明。有关包含各种声明的 actor 的讨论和多个示例,请参见 。 -Actor types can adopt any number of protocols, -but can't inherit from classes, enumerations, structures, or other actors. -However, an actor that is marked with the `@objc` attribute -implicitly conforms to the `NSObjectProtocol` protocol -and is exposed to the Objective-C runtime as a subtype of `NSObject`. +actor 类型可以采用任意数量的协议,但不能从类、枚举、结构体或其他 actor 继承。然而,标记为 `@objc` 特性的 actor 隐式地遵循 `NSObjectProtocol` 协议,并作为 `NSObject` 的子类型暴露给 Objective-C 运行时。 -There are two ways to create an instance of a previously declared actor: +有两种方法可以创建一个先前声明的 actor 的实例: -- Call one of the initializers declared within the actor, - as described in . -- If no initializers are declared, - and all properties of the actor declaration were given initial values, - call the actor's default initializer, - as described in . +- 调用 actor 中声明的某个构造方法,参见 。 +- 如果没有声明初始值,并且 actor 声明的所有属性都给定了初始值,则调用 actor 的默认构造器,参见 。 -By default, members of an actor are isolated to that actor. -Code, such as the body of a method or the getter for a property, -is executed on that actor. -Code within the actor can interact with them synchronously -because that code is already running on the same actor, -but code outside the actor must mark them with `await` -to indicate that this code is asynchronously running code on another actor. -Key paths can't refer to isolated members of an actor. -Actor-isolated stored properties can be passed as in-out parameters -to synchronous functions, -but not to asynchronous functions. +默认情况下,actor 的成员是与该 actor 隔离的。方法体或属性的 getter 等代码是在该 actor 上执行的。actor 内部的代码可以同步地与这些成员交互,因为代码已经在同一个 actor 上运行;但 actor 外部的代码必须使用 `await` 标记,以表明该代码是异步地在另一个 actor 上运行的。键路径不能引用 actor 的隔离成员。actor 隔离的存储属性可以作为 in-out 参数传递给同步函数,但不能传递给异步函数。 -Actors can also have nonisolated members, -whose declarations are marked with the `nonisolated` keyword. -A nonisolated member executes like code outside of the actor: -It can't interact with any of the actor's isolated state, -and callers don't mark it with `await` when using it. +actor 还可以拥有非隔离成员,其声明使用 `nonisolated` 关键字标记。非隔离成员的执行方式类似于 actor 外部的代码:它无法与 actor 的任何隔离状态交互,调用者在使用时也不需要使用 `await` 进行标记。 -Members of an actor can be marked with the `@objc` attribute -only if they are nonisolated or asynchronous. +actor 的成员只有在它们是非隔离或异步的情况下才能标记为 `@objc` 属性。 -The process of initializing an actor's declared properties -is described in . +初始化 actor 中声明的属性的过程,参见 。 -Properties of an actor instance can be accessed using dot (`.`) syntax, -as described in . +actor 实例的属性可以使用点 (`.`) 语法访问,参见 。 -Actors are reference types; instances of an actor are referred to, rather than copied, -when assigned to variables or constants, or when passed as arguments to a function call. -For information about reference types, -see . +actor 是引用类型;当分配给变量或常量,或作为参数传递给函数调用时,actor 的实例是被引用而不是复制。有关引用类型的信息,请参见 。 -You can extend the behavior of an actor type with an extension declaration, -as discussed in . +你可以通过扩展声明扩展 actor 类型的行为,参见 -> Grammar of an actor declaration: +> actor 声明的语法: > > *actor-declaration* → *attributes*_?_ *access-level-modifier*_?_ **`actor`** *actor-name* *generic-parameter-clause*_?_ *type-inheritance-clause*_?_ *generic-where-clause*_?_ *actor-body* \ > *actor-name* → *identifier* \ @@ -2310,63 +1694,28 @@ as discussed in . > *actor-members* → *actor-member* *actor-members*_?_ \ > *actor-member* → *declaration* | *compiler-control-statement* -## Protocol Declaration +## 协议声明 -A *protocol declaration* introduces a named protocol type into your program. -Protocol declarations are declared -using the `protocol` keyword and have the following form: +*协议声明*将一个具名的协议类型引入到你的程序中。协议声明使用 `protocol` 关键字声明,具有以下形式: ```swift protocol <#protocol name#>: <#inherited protocols#> { - <#protocol member declarations#> -} -``` - -Protocol declarations can appear at global scope, -or nested inside a nongeneric type or nongeneric function. - -The body of a protocol contains zero or more *protocol member declarations*, -which describe the conformance requirements that any type adopting the protocol must fulfill. -In particular, a protocol can declare that conforming types must -implement certain properties, methods, initializers, and subscripts. -Protocols can also declare special kinds of type aliases, -called *associated types*, that can specify relationships -among the various declarations of the protocol. -Protocol declarations can't contain -class, structure, enumeration, or other protocol declarations. -The *protocol member declarations* are discussed in detail below. - -Protocol types can inherit from any number of other protocols. -When a protocol type inherits from other protocols, -the set of requirements from those other protocols are aggregated, -and any type that inherits from the current protocol must conform to all those requirements. -For an example of how to use protocol inheritance, -see . - -> Note: You can also aggregate the conformance requirements of multiple -> protocols using protocol composition types, -> as described in -> and . - -You can add protocol conformance to a previously declared type -by adopting the protocol in an extension declaration of that type. -In the extension, you must implement all of the adopted protocol's -requirements. If the type already implements all of the requirements, -you can leave the body of the extension declaration empty. - -By default, types that conform to a protocol must implement all -properties, methods, and subscripts declared in the protocol. -That said, you can mark these protocol member declarations with the `optional` declaration modifier -to specify that their implementation by a conforming type is optional. -The `optional` modifier can be applied -only to members that are marked with the `objc` attribute, -and only to members of protocols that are marked -with the `objc` attribute. As a result, only class types can adopt and conform -to a protocol that contains optional member requirements. -For more information about how to use the `optional` declaration modifier -and for guidance about how to access optional protocol members --- -for example, when you're not sure whether a conforming type implements them --- -see . + <#protocol member declarations#> +} +``` + +协议声明可以出现在全局作用域内,或嵌套在非泛型类型或非泛型函数内部。 + +协议的主体包含零个或多个*协议成员声明*,这些声明描述了任何采用该协议的类型必须满足的遵循性要求。特别是,协议可以声明遵循的类型必须实现某些属性、方法、构造器和下标。协议还可以声明特殊类型的类型别名,称为*关联类型*,可以指定协议中各种声明之间的关系。协议声明不能包含类、结构体、枚举或其他协议声明。*协议成员声明*将在下面详细讨论。 + +协议类型可以从任意数量的其他协议继承。当一个协议类型从其他协议继承时,这些其他协议的要求集合会被聚合,任何从当前协议继承的类型必须遵循所有这些要求。有关如何使用协议继承的示例,请参见 。 + +> 注意: +> 你还可以使用协议组合类型聚合多个协议的合规性要求,参见 。 + +你可以通过在该类型的扩展声明中采用协议,为先前声明的类型添加协议遵循性。在扩展中,你必须实现所采用协议的所有要求。如果该类型已经实现了所有要求,你可以将扩展声明的主体留空。 + +默认情况下,遵循协议的类型必须实现协议中声明的所有属性、方法和下标。也就是说,你可以使用 `optional` 声明修饰符来标记这些协议成员声明,以指定遵循类型的实现是可选的。`optional` 修饰符只能应用于标记为 `objc` 特性的成员,并且只能应用于标记为 `objc` 特性的协议成员。因此,只有类类型可以采用并遵循包含可选成员要求的协议。有关如何使用 `optional` 声明修饰符的信息,以及如何访问可选协议成员的指导——例如,当你不确定遵循类型是否实现它们时——请参见 -The cases of an enumeration can satisfy -protocol requirements for type members. -Specifically, -an enumeration case without any associated values -satisfies a protocol requirement for -a get-only type variable of type `Self`, -and an enumeration case with associated values -satisfies a protocol requirement for a function that returns `Self` -whose parameters and their argument labels -match the case's associated values. -For example: +枚举的用例可以满足类型成员的协议要求。具体来说,没有任何关联值的枚举用例满足类型 `Self` 的只读类型变量的协议要求,而具有关联值的枚举成员满足返回 `Self` 的函数的协议要求,该函数的参数及其实参标签与枚举成员的关联值匹配。例如: ```swift protocol SomeProtocol { @@ -2414,14 +1753,11 @@ enum MyEnum: SomeProtocol { ``` --> -To restrict the adoption of a protocol to class types only, -include the `AnyObject` protocol in the *inherited protocols* -list after the colon. -For example, the following protocol can be adopted only by class types: +要将协议的采用限制为类类型,只需在冒号后将 `AnyObject` 协议包含在*继承协议*列表中。例如,以下协议只能被类类型采用: ```swift protocol SomeProtocol: AnyObject { - /* Protocol members go here */ + /* 协议成员写在这里 */ } ``` @@ -2435,24 +1771,16 @@ protocol SomeProtocol: AnyObject { ``` --> -Any protocol that inherits from a protocol that's marked with the `AnyObject` requirement -can likewise be adopted only by class types. +任何从标记为 `AnyObject` 要求的协议继承的协议,也只能被类类型采用。 -> Note: If a protocol is marked with the `objc` attribute, -> the `AnyObject` requirement is implicitly applied to that protocol; -> there’s no need to mark the protocol with the `AnyObject` requirement explicitly. +> 注意: +> 如果一个协议标记了 `objc` 特性,则 `AnyObject` 要求隐式应用于该协议;无需显式的将该协议标记为 `AnyObject` 要求。 -Protocols are named types, and thus they can appear in all the same places -in your code as other named types, as discussed in . -However, -you can't construct an instance of a protocol, -because protocols don't actually provide the implementations for the requirements -they specify. +协议是具名类型,因此它们可以出现在代码中与其他具名类型相同的位置,如 中所讨论的。然而,你无法构造协议的实例,因为协议实际上并不提供它们所指定的要求的实现。 -You can use protocols to declare which methods a delegate of a class or structure -should implement, as described in . +你可以使用协议来声明类或结构体的代理应该实现哪些方法,参见 。 -> Grammar of a protocol declaration: +> 协议声明的语法: > > *protocol-declaration* → *attributes*_?_ *access-level-modifier*_?_ **`protocol`** *protocol-name* *type-inheritance-clause*_?_ *generic-where-clause*_?_ *protocol-body* \ > *protocol-name* → *identifier* \ @@ -2468,44 +1796,19 @@ should implement, as described in . > *protocol-member-declaration* → *protocol-associated-type-declaration* \ > *protocol-member-declaration* → *typealias-declaration* -### Protocol Property Declaration +### 协议属性声明 -Protocols declare that conforming types must implement a property -by including a *protocol property declaration* -in the body of the protocol declaration. -Protocol property declarations have a special form of a variable -declaration: +协议通过在协议声明体中包含一个*协议属性声明*,规定遵循该协议的类型必须实现一个属性。协议属性声明是一种特殊形式的变量声明,格式如下: ```swift var <#property name#>: <#type#> { get set } ``` -As with other protocol member declarations, these property declarations -declare only the getter and setter requirements for types -that conform to the protocol. As a result, you don't implement the getter or setter -directly in the protocol in which it's declared. - -The getter and setter requirements can be satisfied by a conforming type in a variety of ways. -If a property declaration includes both the `get` and `set` keywords, -a conforming type can implement it with a stored variable property -or a computed property that's both readable and writeable -(that is, one that implements both a getter and a setter). However, -that property declaration can't be implemented as a constant property -or a read-only computed property. If a property declaration includes -only the `get` keyword, it can be implemented as any kind of property. -For examples of conforming types that implement the property requirements of a protocol, -see . - -To declare a type property requirement in a protocol declaration, -mark the property declaration with the `static` keyword. -Structures and enumerations that conform to the protocol -declare the property with the `static` keyword, -and classes that conform to the protocol -declare the property with either the `static` or `class` keyword. -Extensions that add protocol conformance to a structure, enumeration, or class -use the same keyword as the type they extend uses. -Extensions that provide a default implementation for a type property requirement -use the `static` keyword. +与其他协议成员声明一样,这些属性声明仅声明遵循该协议的类型的 getter 和 setter 要求。因此,你不会在声明它的协议中直接实现 getter 或 setter。 + +遵循协议的类型可以通过多种方式满足 getter 和 setter 的要求。如果属性声明同时包含 `get` 和 `set` 关键字,遵循类型可以用存储变量属性或可读写的计算属性(即实现了 getter 和 setter 的属性)来实现。然而,这样的属性声明不能被实现为常量属性或只读计算属性。如果属性声明只包含 `get` 关键字,则可以实现为任何类型的属性。关于符合协议类型如何实现属性要求的示例,参见 。 + +在协议声明中声明类型属性要求时,使用 `static` 关键字标记属性声明。遵循该协议的结构体和枚举使用 `static` 关键字声明属性,而遵循该协议的类则可以使用 `static` 或 `class` 关键字声明属性。为结构体、枚举或类添加协议遵循的扩展使用与其扩展的类型相同的关键字。为类型属性要求提供默认实现的扩展使用 `static` 关键字。 -See also . +另见 。 -> Grammar of a protocol property declaration: +> 协议属性声明的语法: > > *protocol-property-declaration* → *variable-declaration-head* *variable-name* *type-annotation* *getter-setter-keyword-block* -### Protocol Method Declaration +### 协议方法声明 -Protocols declare that conforming types must implement a method -by including a protocol method declaration in the body of the protocol declaration. -Protocol method declarations have the same form as -function declarations, with two exceptions: They don't include a function body, -and you can't provide any default parameter values as part of the function declaration. -For examples of conforming types that implement the method requirements of a protocol, -see . +协议通过在协议声明体中包含一个协议方法声明,规定遵循该协议的类型必须实现一个方法。协议方法声明的形式与函数声明相同,但有两个例外:它们不包含函数体,且不能在函数声明中提供任何默认参数值。关于遵循协议类型如何实现方法要求的示例,参见 。 -To declare a class or static method requirement in a protocol declaration, -mark the method declaration with the `static` declaration modifier. -Structures and enumerations that conform to the protocol -declare the method with the `static` keyword, -and classes that conform to the protocol -declare the method with either the `static` or `class` keyword. -Extensions that add protocol conformance to a structure, enumeration, or class -use the same keyword as the type they extend uses. -Extensions that provide a default implementation for a type method requirement -use the `static` keyword. +在协议声明中声明类或静态方法的要求时,使用 `static` 修饰符标记方法声明。遵循该协议的结构体和枚举使用 `static` 关键字声明该方法,而遵循该协议的类则使用 `static` 或 `class` 关键字声明该方法。为结构体、枚举或类添加协议遵循的扩展使用与其扩展的类型相同的关键字。为类型方法要求提供默认实现的扩展使用 `static` 关键字。 -See also . +另见 -> Grammar of a protocol method declaration: +> 协议方法声明的语法: > > *protocol-method-declaration* → *function-head* *function-name* *generic-parameter-clause*_?_ *function-signature* *generic-where-clause*_?_ -### Protocol Initializer Declaration +### 协议构造器声明 -Protocols declare that conforming types must implement an initializer -by including a protocol initializer declaration in the body of the protocol declaration. -Protocol initializer declarations have the same form as -initializer declarations, except they don't include the initializer's body. +协议通过在协议声明的主体中包含协议构造器声明,要求遵循的类型必须实现一个构造器。协议构造器声明的形式与构造器声明相同,只是不包括构造器的主体。 -A conforming type can satisfy a nonfailable protocol initializer requirement -by implementing a nonfailable initializer or an `init!` failable initializer. -A conforming type can satisfy a failable protocol initializer requirement -by implementing any kind of initializer. +遵循类型可以通过实现一个非可失败构造器或一个 `init!` 可失败构造器来满足非可失败协议构造器的要求。一个遵循类型可以通过实现任何类型的构造器来满足可失败协议构造器的要求。 -When a class implements an initializer to satisfy a protocol's initializer requirement, -the initializer must be marked with the `required` declaration modifier -if the class isn't already marked with the `final` declaration modifier. +当一个类实现一个构造器以满足协议的构造器要求时,如果该类尚未标记为 `final` 声明修饰符,则构造器必须标记为 `required` 声明修饰符。 -See also . +另见 。 -> Grammar of a protocol initializer declaration: +> 协议构造器声明的语法: > > *protocol-initializer-declaration* → *initializer-head* *generic-parameter-clause*_?_ *parameter-clause* *throws-clause*_?_ *generic-where-clause*_?_ \ > *protocol-initializer-declaration* → *initializer-head* *generic-parameter-clause*_?_ *parameter-clause* **`rethrows`** *generic-where-clause*_?_ -### Protocol Subscript Declaration +### 协议下标声明 -Protocols declare that conforming types must implement a subscript -by including a protocol subscript declaration in the body of the protocol declaration. -Protocol subscript declarations have a special form of a subscript declaration: +协议声明遵循的类型必须通过在协议声明的主体中包含协议下标声明来实现下标。协议下标声明具有下标声明的特殊形式: ```swift subscript (<#parameters#>) -> <#return type#> { get set } ``` -Subscript declarations only declare the minimum getter and setter implementation -requirements for types that conform to the protocol. -If the subscript declaration includes both the `get` and `set` keywords, -a conforming type must implement both a getter and a setter clause. -If the subscript declaration includes only the `get` keyword, -a conforming type must implement *at least* a getter clause -and optionally can implement a setter clause. - -To declare a static subscript requirement in a protocol declaration, -mark the subscript declaration with the `static` declaration modifier. -Structures and enumerations that conform to the protocol -declare the subscript with the `static` keyword, -and classes that conform to the protocol -declare the subscript with either the `static` or `class` keyword. -Extensions that add protocol conformance to a structure, enumeration, or class -use the same keyword as the type they extend uses. -Extensions that provide a default implementation for a static subscript requirement -use the `static` keyword. - -See also . - -> Grammar of a protocol subscript declaration: +下标声明仅声明遵循协议的类型所需的最小 getter 和 setter 实现要求。如果下标声明同时包含 `get` 和 `set` 关键字,则遵循的类型必须实现 getter 和 setter 子句。如果下标声明仅包含 `get` 关键字,则遵循的类型必须实现*至少*一个 getter 子句,并且可以选择性地实现一个 setter 子句。 + +在协议声明中声明静态下标要求时,使用 `static` 声明修饰符标记下标声明。遵循该协议的结构体和枚举使用 `static` 关键字声明下标,而遵循该协议的类则使用 `static` 或 `class` 关键字声明下标。为结构体、枚举或类添加协议遵循性的扩展使用与其扩展的类型相同的关键字。为静态下标要求提供默认实现的扩展使用 `static` 关键字。 + +另见 。 + +> 协议下标声明的语法: > > *protocol-subscript-declaration* → *subscript-head* *subscript-result* *generic-where-clause*_?_ *getter-setter-keyword-block* -### Protocol Associated Type Declaration +### 协议关联类型声明 -Protocols declare associated types using the `associatedtype` keyword. -An associated type provides an alias for a type -that's used as part of a protocol's declaration. -Associated types are similar to type parameters in generic parameter clauses, -but they're associated with `Self` in the protocol in which they're declared. -In that context, `Self` refers to the eventual type that conforms to the protocol. -For more information and examples, -see . +协议使用 `associatedtype` 关键字声明关联类型。关联类型为作为协议声明一部分使用的类型提供了别名。关联类型类似于泛型参数子句中的类型参数,但它们与声明它们的协议中的 `Self` 相关联。在该上下文中,`Self` 指的是遵循该协议的最终类型。有关更多信息和示例,请参见 。 -You use a generic `where` clause in a protocol declaration -to add constraints to an associated types inherited from another protocol, -without redeclaring the associated types. -For example, the declarations of `SubProtocol` below are equivalent: +你在协议声明中使用通用的 `where` 子句,以便为从另一个协议继承的关联类型添加约束,而无需重新声明关联类型。以下 `SubProtocol` 的声明是等效的: ```swift protocol SomeProtocol { @@ -2658,11 +1911,11 @@ protocol SomeProtocol { } protocol SubProtocolA: SomeProtocol { - // This syntax produces a warning. + // 此语法会产生警告。 associatedtype SomeType: Equatable } -// This syntax is preferred. +// 推荐使用此语法。 protocol SubProtocolB: SomeProtocol where SomeType: Equatable { } ``` @@ -2760,112 +2013,68 @@ protocol SubProtocolB: SomeProtocol where SomeType: Equatable { } Here you have to pick one or the other -- you can't have both. --> -See also . +另见 。 -> Grammar of a protocol associated type declaration: +> 协议关联类型声明的语法: > > *protocol-associated-type-declaration* → *attributes*_?_ *access-level-modifier*_?_ **`associatedtype`** *typealias-name* *type-inheritance-clause*_?_ *typealias-assignment*_?_ *generic-where-clause*_?_ -## Initializer Declaration +## 构造器声明 -An *initializer declaration* introduces an initializer for a class, -structure, or enumeration into your program. -Initializer declarations are declared using the `init` keyword and have -two basic forms. +*构造器声明*在你的程序中引入了一个类、结构体或枚举的构造器。构造器声明使用 `init` 关键字声明,有两种基本形式。 -Structure, enumeration, and class types can have any number of initializers, -but the rules and associated behavior for class initializers are different. -Unlike structures and enumerations, classes have two kinds of initializers: -designated initializers and convenience initializers, -as described in . +结构体、枚举和类类型可以有任意数量的构造器,但是类的构造器具有不同的规则和行为。与结构体和枚举不同,类有两种类型的构造器:指定构造器和便利构造器,参见 。 -The following form declares initializers for structures, enumerations, -and designated initializers of classes: +以下形式声明了结构体和枚举的构造器,以及类的指定构造器:: ```swift init(<#parameters#>) { - <#statements#> + <#statements#> } ``` -A designated initializer of a class initializes -all of the class's properties directly. It can't call any other initializers -of the same class, and if the class has a superclass, it must call one of -the superclass's designated initializers. -If the class inherits any properties from its superclass, one of the -superclass's designated initializers must be called before any of these -properties can be set or modified in the current class. +类的指定构造器直接初始化类的所有属性。它不能调用当前类的其他构造器,如果该类有一个超类,则必须调用超类的一个指定构造器。如果该类从其超类继承了任何属性,则在当前类中设置或修改这些属性之前,必须调用超类的一个指定构造器。 -Designated initializers can be declared in the context of a class declaration only -and therefore can't be added to a class using an extension declaration. +指定构造器只能在类声明中声明,因此不能通过扩展声明添加到类中。 -Initializers in structures and enumerations can call other declared initializers -to delegate part or all of the initialization process. +结构体和枚举中的构造器可以调用其他已声明的构造器,以委托部分或全部初始化过程。 -To declare convenience initializers for a class, -mark the initializer declaration with the `convenience` declaration modifier. +要为一个类声明便利构造器,请使用 `convenience` 声明修饰符标记构造器声明。 ```swift convenience init(<#parameters#>) { - <#statements#> + <#statements#> } ``` -Convenience initializers can delegate the initialization process to another -convenience initializer or to one of the class's designated initializers. -That said, the initialization processes must end with a call to a designated -initializer that ultimately initializes the class's properties. -Convenience initializers can't call a superclass's initializers. +便利构造器可以将构造过程委托给另一个便利构造器或一个指定构造器。但是,类的构造过程必须以一个将类中所有属性完全初始化的指定构造器的调用作为结束。便利构造器不能调用超类的构造器 -You can mark designated and convenience initializers with the `required` -declaration modifier to require that every subclass implement the initializer. -A subclass’s implementation of that initializer -must also be marked with the `required` declaration modifier. +你可以使用 `required` 声明修饰符标记指定和便利构造器,以要求每个子类实现该构造器。子类对该构造器的实现也必须标记为 `required` 声明修饰符。 -By default, initializers declared in a superclass -aren't inherited by subclasses. -That said, if a subclass initializes all of its stored properties with default values -and doesn't define any initializers of its own, -it inherits all of the superclass's initializers. -If the subclass overrides all of the superclass’s designated initializers, -it inherits the superclass’s convenience initializers. +默认情况下,超类中声明的构造器不会被子类继承。也就是说,如果子类用默认值初始化了所有存储属性,并且没有定义自己的构造器,它将继承超类的所有构造器。如果子类重写了超类的所有指定构造器,它将继承超类的便利构造器。 -As with methods, properties, and subscripts, -you need to mark overridden designated initializers with the `override` declaration modifier. +与方法、属性和下标一样,你需要使用 `override` 声明修饰符标记重写的指定构造器。 -> Note: If you mark an initializer with the `required` declaration modifier, -> you don't also mark the initializer with the `override` modifier -> when you override the required initializer in a subclass. +> 注意: +> 如果你使用 `required` 声明修饰符标记了一个构造器,则在子类中重写所需的构造器时,不要同时使用 `override` 修饰符标记该构造器。 -Just like functions and methods, initializers can throw or rethrow errors. -And just like functions and methods, -you use the `throws` or `rethrows` keyword after an initializer's parameters -to indicate the appropriate behavior. -Likewise, initializers can be asynchronous, -and you use the `async` keyword to indicate this. +就像函数和方法一样,构造器可以抛出或再抛出错误。与函数和方法一样,你在构造器的参数后使用 `throws` 或 `rethrows` 关键字来指示适当的行为。同样,构造器可以是异步的,你使用 `async` 关键字来指示这一点。 -To see examples of initializers in various type declarations, -see . +要查看各种类型声明中构造器的示例,请参见 。 -### Failable Initializers +### 可失败的构造器 -A *failable initializer* is a type of initializer that produces an optional instance -or an implicitly unwrapped optional instance of the type the initializer is declared on. -As a result, a failable initializer can return `nil` to indicate that initialization failed. +*可失败的构造器*是一种生成一个可选实例或一个隐式解包的可选实例的构造器,具体取决于构造器声明的类型。因此,可失败的构造器可以返回 `nil` 以表示初始化失败。 -To declare a failable initializer that produces an optional instance, -append a question mark to the `init` keyword in the initializer declaration (`init?`). -To declare a failable initializer that produces an implicitly unwrapped optional instance, -append an exclamation point instead (`init!`). The example below shows an `init?` -failable initializer that produces an optional instance of a structure. +要声明一个可失败的构造器并生成一个可选实例,需要在构造器声明中的 `init` 关键字后面加上问号(`init?`)。要声明一个可失败构造器并生成一个隐式解包的可选实例,则需要加上感叹号(`init!`)。下面的示例展示了一个 `init?` 可失败的构造器,它生成了一个结构体的可选实例。 ```swift struct SomeStruct { let property: String - // produces an optional instance of 'SomeStruct' + // 生成一个 `SomeStruct` 可选实例 init?(input: String) { if input.isEmpty { - // discard 'self' and return 'nil' + // 丢弃 'self' 并返回 'nil' return nil } property = input @@ -2891,14 +2100,13 @@ struct SomeStruct { ``` --> -You call an `init?` failable initializer in the same way that you call a nonfailable initializer, -except that you must deal with the optionality of the result. +调用 `init?` 可失败的构造器与调用不可失败的构造器的方式相同,只是你必须处理结果的可选性。 ```swift if let actualInstance = SomeStruct(input: "Hello") { - // do something with the instance of 'SomeStruct' + // 使用 'SomeStruct' 的实例执行操作 } else { - // initialization of 'SomeStruct' failed and the initializer returned 'nil' + // 'SomeStruct' 的初始化失败,初始化器返回了 'nil' } ``` @@ -2915,33 +2123,17 @@ if let actualInstance = SomeStruct(input: "Hello") { ``` --> -A failable initializer can return `nil` -at any point in the implementation of the initializer's body. +可失败的构造器可以在构造器主体的实现中的任何时刻返回 `nil`。 -A failable initializer can delegate to any kind of initializer. -A nonfailable initializer can delegate to another nonfailable initializer -or to an `init!` failable initializer. -A nonfailable initializer can delegate to an `init?` failable initializer -by force-unwrapping the result of the superclass's initializer --- -for example, by writing `super.init()!`. +可失败的构造器可以委托给任何类型的构造器。不可失败的构造器可以委托给另一个不可失败的构造器或一个 `init!` 可失败的构造器。不可失败的构造器可以通过强制解包超类构造器的结果来委托给一个 `init?` 可失败的构造器——例如,通过写 `super.init()!`。 -Initialization failure propagates through initializer delegation. -Specifically, -if a failable initializer delegates to an initializer that fails and returns `nil`, -then the initializer that delegated also fails and implicitly returns `nil`. -If a nonfailable initializer delegates to an `init!` failable initializer that fails and returns `nil`, -then a runtime error is raised -(as if you used the `!` operator to unwrap an optional that has a `nil` value). +初始化失败会通过构造器委托传播。具体来说,如果一个可失败的构造器委托给一个失败并返回 `nil` 的构造器,那么委托的构造器也会失败并隐式返回 `nil`。如果一个不可失败的构造器委托给一个失败并返回 `nil` 的 `init!` 可失败构造器,那么会引发运行时错误(就像你使用`!`运算符来解包一个值为 `nil`的可选值一样)。 -A failable designated initializer can be overridden in a subclass -by any kind of designated initializer. -A nonfailable designated initializer can be overridden in a subclass -by a nonfailable designated initializer only. +可失败的指定构造器可以在子类中被任何类型的指定构造器重写。不可失败的指定构造器只能在子类中被不可失败的指定构造器重写。 -For more information and to see examples of failable initializers, -see . +有关更多信息以及可失败构造器的示例,请参见 。 -> Grammar of an initializer declaration: +> 初始化声明的语法: > > *initializer-declaration* → *initializer-head* *generic-parameter-clause*_?_ *parameter-clause* **`async`**_?_ *throws-clause*_?_ *generic-where-clause*_?_ *initializer-body* \ > *initializer-declaration* → *initializer-head* *generic-parameter-clause*_?_ *parameter-clause* **`async`**_?_ **`rethrows`** *generic-where-clause*_?_ *initializer-body* \ @@ -2950,111 +2142,65 @@ see . > *initializer-head* → *attributes*_?_ *declaration-modifiers*_?_ **`init`** **`!`** \ > *initializer-body* → *code-block* -## Deinitializer Declaration +## 析构器声明 -A *deinitializer declaration* declares a deinitializer for a class type. -Deinitializers take no parameters and have the following form: +*析构器声明*为类类型声明一个析构器。析构器不接受参数,具有以下形式: ```swift deinit { - <#statements#> + <#statements#> } ``` -A deinitializer is called automatically when there are no longer any references -to a class object, just before the class object is deallocated. -A deinitializer can be declared only in the body of a class declaration --- -but not in an extension of a class --- -and each class can have at most one. +析构器在一个类对象不再有任何引用时,会在该对象被释放之前自动调用。析构器只能在类声明的主体内声明,不能在类的扩展中声明,并且每个类最多只能有一个析构器 -A subclass inherits its superclass's deinitializer, -which is implicitly called just before the subclass object is deallocated. -The subclass object isn't deallocated until all deinitializers in its inheritance chain -have finished executing. +子类继承其超类的析构器,该析构器在子类对象被释放之前隐式调用。子类对象在其继承链中的所有析构器执行完毕之前不会被释放。 -Deinitializers aren't called directly. +析构器不会被直接调用。 -For an example of how to use a deinitializer in a class declaration, -see . +在类声明中如何使用析构器的示例,请参见 。 -> Grammar of a deinitializer declaration: +> 析构器声明的语法: > > *deinitializer-declaration* → *attributes*_?_ **`deinit`** *code-block* -## Extension Declaration +## 扩展声明 -An *extension declaration* allows you to extend -the behavior of existing types. -Extension declarations are declared using the `extension` keyword -and have the following form: +*扩展声明*允许你扩展现有类型的行为。扩展声明使用 `extension` 关键字声明,具有以下形式: ```swift extension <#type name#> where <#requirements#> { - <#declarations#> + <#declarations#> } ``` -The body of an extension declaration contains zero or more *declarations*. -These *declarations* can include computed properties, computed type properties, -instance methods, type methods, initializers, subscript declarations, -and even class, structure, and enumeration declarations. -Extension declarations can't contain deinitializer or protocol declarations, -stored properties, property observers, or other extension declarations. -Declarations in a protocol extension can't be marked `final`. -For a discussion and several examples of extensions that include various kinds of declarations, -see . +扩展声明的主体包含零个或多个*声明*。这些*声明*可以包括计算属性、计算类型属性、实例方法、类型方法、构造器、下标声明,甚至类、结构体和枚举声明。扩展声明不能包含析构器或协议声明、存储属性、属性观察者或其他扩展声明。协议扩展中的声明不能标记为 `final`。有关包含各种类型声明的扩展的讨论和多个示例,请参见 。 -If the *type name* is a class, structure, or enumeration type, -the extension extends that type. -If the *type name* is a protocol type, -the extension extends all types that conform to that protocol. +如果*类型名称*是类、结构体或枚举类型,则扩展该类型。如果*类型名称*是协议类型,则扩展所有遵循该协议的类型。 -Extension declarations that extend a generic type -or a protocol with associated types -can include *requirements*. -If an instance of the extended type -or of a type that conforms to the extended protocol -satisfies the *requirements*, -the instance gains the behavior specified in the declaration. +扩展声明可以扩展具有关联类型的泛型类型或协议,并可以包含*要求*。如果扩展类型的实例或遵循扩展协议的类型的实例满足*要求*,则该实例获得声明中指定的行为。 -Extension declarations can contain initializer declarations. That said, -if the type you're extending is defined in another module, -an initializer declaration must delegate to an initializer already defined in that module -to ensure members of that type are properly initialized. +扩展声明可以包含构造器声明。也就是说,如果你正在扩展的类型在另一个模块中定义,则构造器声明必须委托给该模块中已定义的构造器,以确保该类型的成员得到正确初始化。 -Properties, methods, and initializers of an existing type -can't be overridden in an extension of that type. +现有类型的属性、方法和构造器不能在该类型的扩展中被重写。 -Extension declarations can add protocol conformance to an existing -class, structure, or enumeration type by specifying *adopted protocols*: +扩展声明可以通过指定*采用的协议*,为现有的类、结构体或枚举类型添加协议遵循: ```swift extension <#type name#>: <#adopted protocols#> where <#requirements#> { - <#declarations#> + <#declarations#> } ``` -Extension declarations can't add class inheritance to an existing class, -and therefore you can specify only a list of protocols after the *type name* and colon. +扩展声明不能为现有类添加类继承,因此你只能在*类型名称*和冒号后指定协议列表。 -### Conditional Conformance +### 条件遵循 -You can extend a generic type -to conditionally conform to a protocol, -so that instances of the type conform to the protocol -only when certain requirements are met. -You add conditional conformance to a protocol -by including *requirements* in an extension declaration. +你可以扩展一个泛型类型以有条件地遵循一个协议,从而使该类型的实例仅在满足某些要求时遵循该协议。你通过在扩展声明中包含*要求*来添加对协议的条件遵循。 -#### Overridden Requirements Aren't Used in Some Generic Contexts +#### 重写的要求在某些泛型上下文中不会被使用 -In some generic contexts, -types that get behavior from conditional conformance to a protocol -don't always use the specialized implementations -of that protocol's requirements. -To illustrate this behavior, -the following example defines two protocols -and a generic type that conditionally conforms to both protocols. +在某些泛型上下文中,通过条件遵循协议而获得行为的类型,并不总是使用该协议要求的特定实现。为了说明这种行为,以下示例定义了两个协议和一个有条件地遵循这两个协议的泛型类型。 -The `Pair` structure conforms to `Loggable` and `TitledLoggable` -whenever its generic type conforms to `Loggable` or `TitledLoggable`, respectively. -In the example below, -`oneAndTwo` is an instance of `Pair`, -which conforms to `TitledLoggable` -because `String` conforms to `TitledLoggable`. -When the `log()` method is called on `oneAndTwo` directly, -the specialized version containing the title string is used. +`Pair` 结构体在其泛型类型分别遵循 `Loggable` 或 `TitledLoggable` 时,也会相应地遵循 `Loggable` 和 `TitledLoggable`。在下面的示例中,`oneAndTwo` 是 `Pair` 的一个实例,由于 `String` 遵循 `TitledLoggable`,因此 `oneAndTwo` 也遵循 `TitledLoggable`。当直接调用 `oneAndTwo` 的 `log()` 方法时,将使用包含标题字符串的特定版本。 ```swift let oneAndTwo = Pair(first: "one", second: "two") oneAndTwo.log() -// Prints "Pair of 'String': (one, two)" +// 打印 "Pair of 'String': (one, two)" ``` -However, when `oneAndTwo` is used in a generic context -or as an instance of the `Loggable` protocol, -the specialized version isn't used. -Swift picks which implementation of `log()` to call -by consulting only the minimum requirements that `Pair` needs to conform to `Loggable`. -For this reason, -the default implementation provided by the `Loggable` protocol is used instead. +然而,当在泛型上下文中使用 `oneAndTwo` 或将其作为 `Loggable` 协议的一个实例时,特定的实现版本不会被使用。Swift 在选择调用哪个 `log()` 实现时,只参考 `Pair` 遵循 `Loggable` 所需的最低要求。因此,使用的是 `Loggable` 协议提供的默认实现。 ```swift func doSomething(with x: T) { x.log() } doSomething(with: oneAndTwo) -// Prints "(one, two)" +// 打印 "(one, two)" ``` -When `log()` is called on the instance that's passed to `doSomething(_:)`, -the customized title is omitted from the logged string. +当在传递给 `doSomething(_:)` 的实例上调用 `log()` 时,自定义标题会从日志字符串中省略。 -### Protocol Conformance Must Not Be Redundant +### 协议的遵循不应冗余 -A concrete type can conform to a particular protocol only once. -Swift marks redundant protocol conformances as an error. -You're likely to encounter this kind of error -in two kinds of situations. -The first situation is when -you explicitly conform to the same protocol multiple times, -but with different requirements. -The second situation is when -you implicitly inherit from the same protocol multiple times. -These situations are discussed in the sections below. +具体类型只能遵从某个协议一次。Swift 会将多余的协议遵从标记为错误。你可能会在两种情况下遇到这种错误。第一种情况是,当你以不同的要求多次显式地遵从同一个协议。第二种情况是,当你多次隐式地继承同一个协议。以下部分将讨论这些情况。 -#### Resolving Explicit Redundancy +#### 解决显式冗余 -Multiple extensions on a concrete type -can't add conformance to the same protocol, -even if the extensions' requirements are mutually exclusive. -This restriction is demonstrated in the example below. -Two extension declarations attempt to add conditional conformance -to the `Serializable` protocol, -one for arrays with `Int` elements, -and one for arrays with `String` elements. +对一个具体类型的多个扩展不能添加对同一协议的遵循,即使这些扩展的要求是互斥的。以下示例展示了这一限制。两个扩展声明试图为 `Serializable` 协议添加条件遵循,一个是针对包含 `Int` 元素的数组,另一个是针对包含 `String` 元素的数组。 ```swift protocol Serializable { @@ -3235,15 +2351,15 @@ protocol Serializable { extension Array: Serializable where Element == Int { func serialize() -> Any { - // implementation + // 实现 } } extension Array: Serializable where Element == String { func serialize() -> Any { - // implementation + // 实现 } } -// Error: redundant conformance of 'Array' to protocol 'Serializable' +// 错误:'Array' 对协议 'Serializable' 的遵循是多余的 ``` -If you need to add conditional conformance based on multiple concrete types, -create a new protocol that each type can conform to -and use that protocol as the requirement when declaring conditional conformance. +如果你需要根据多个具体类型添加条件遵循,请创建一个每个类型都可以遵循的新协议,并在声明条件遵循时使用该协议作为要求。 ```swift protocol SerializableInArray { } @@ -3287,7 +2401,7 @@ extension String: SerializableInArray { } extension Array: Serializable where Element: SerializableInArray { func serialize() -> Any { - // implementation + // 实现 } } ``` @@ -3310,22 +2424,13 @@ extension Array: Serializable where Element: SerializableInArray { ``` --> -#### Resolving Implicit Redundancy +#### 解决隐式冗余 -When a concrete type conditionally conforms to a protocol, -that type implicitly conforms to any parent protocols -with the same requirements. +当一个具体类型有条件地遵循一个协议时,该类型隐式地遵循任何具有相同要求的父协议。 -If you need a type to conditionally conform to two protocols -that inherit from a single parent, -explicitly declare conformance to the parent protocol. -This avoids implicitly conforming to the parent protocol twice -with different requirements. +如果你需要一个类型有条件地遵循两个继承自单一父协议的协议,请显式声明对父协议的遵循。这可以避免以不同的要求隐式地两次遵循父协议。 -The following example explicitly declares -the conditional conformance of `Array` to `Loggable` -to avoid a conflict when declaring its conditional conformance -to both `TitledLoggable` and the new `MarkedLoggable` protocol. +以下示例显式声明了 `Array` 对 `Loggable` 的条件遵循,以避免在声明其对 `TitledLoggable` 和新的 `MarkedLoggable` 协议的条件遵循时发生冲突。 ```swift protocol MarkedLoggable: Loggable { @@ -3373,15 +2478,12 @@ extension Array: MarkedLoggable where Element: MarkedLoggable { } ``` --> -Without the extension -to explicitly declare conditional conformance to `Loggable`, -the other `Array` extensions would implicitly create these declarations, -resulting in an error: +在没有扩展显式声明对 `Loggable` 的条件遵循时,其他 `Array` 扩展会隐式创建这些声明,从而导致错误: ```swift extension Array: Loggable where Element: TitledLoggable { } extension Array: Loggable where Element: MarkedLoggable { } -// Error: redundant conformance of 'Array' to protocol 'Loggable' +// 错误:'Array' 对协议 'Loggable' 的遵循是多余的 ``` -> Grammar of an extension declaration: +> 扩展声明的语法: > > *extension-declaration* → *attributes*_?_ *access-level-modifier*_?_ **`extension`** *type-identifier* *type-inheritance-clause*_?_ *generic-where-clause*_?_ *extension-body* \ > *extension-body* → **`{`** *extension-members*_?_ **`}`** @@ -3473,79 +2575,40 @@ extension Array: Loggable where Element: MarkedLoggable { } > *extension-members* → *extension-member* *extension-members*_?_ \ > *extension-member* → *declaration* | *compiler-control-statement* -## Subscript Declaration +## 下标声明 -A *subscript* declaration allows you to add subscripting support for objects -of a particular type and are typically used to provide a convenient syntax -for accessing the elements in a collection, list, or sequence. -Subscript declarations are declared using the `subscript` keyword -and have the following form: +*下标*声明允许你为特定类型的对象添加下标支持,通常用于提供一种方便的语法来访问集合、列表或序列中的元素。下标声明使用 `subscript` 关键字声明,具有以下形式: ```swift subscript (<#parameters#>) -> <#return type#> { - get { - <#statements#> - } - set(<#setter name#>) { - <#statements#> - } + get { + <#statements#> + } + set(<#setter name#>) { + <#statements#> + } } ``` -Subscript declarations can appear only in the context of a class, structure, -enumeration, extension, or protocol declaration. +下标声明只能出现在类、结构体、枚举、扩展或协议声明的上下文中。 -The *parameters* specify one or more indexes used to access elements of the corresponding type -in a subscript expression (for example, the `i` in the expression `object[i]`). -Although the indexes used to access the elements can be of any type, -each parameter must include a type annotation to specify the type of each index. -The *return type* specifies the type of the element being accessed. +*参数*指定了在下标表达式中用于访问对应类型元素的一个或多个索引(例如,在表达式 `object[i]` 中的 `i`)。尽管用于访问元素的索引可以是任意类型,但每个参数都必须包含一个类型注释,以指定每个索引的类型。*返回类型*指定了被访问元素的类型。 -As with computed properties, -subscript declarations support reading and writing the value of the accessed elements. -The getter is used to read the value, -and the setter is used to write the value. -The setter clause is optional, -and when only a getter is needed, you can omit both clauses and simply -return the requested value directly. -That said, if you provide a setter clause, you must also provide a getter clause. +与计算属性一样,下标声明支持读取和写入所访问元素的值。getter 用于读取值,setter 用于写入值。setter 子句是可选的,当只需要 getter 时,可以省略两个子句,直接返回请求的值。也就是说,如果提供了 setter 子句,则必须同时提供 getter 子句。 -The *setter name* and enclosing parentheses are optional. -If you provide a setter name, it's used as the name of the parameter to the setter. -If you don't provide a setter name, the default parameter name to the setter is `value`. -The type of the parameter to the setter is the same as the *return type*. +*setter 名称*和括号是可选的。如果你提供了 setter 名称,它将用作 setter 的参数名称。如果你不提供 setter 名称,setter 的默认参数名称是 `value`。setter 的参数类型与*返回类型*相同。 -You can overload a subscript declaration in the type in which it's declared, -as long as the *parameters* or the *return type* differ from the one you're overloading. -You can also override a subscript declaration inherited from a superclass. When you do so, -you must mark the overridden subscript declaration with the `override` declaration modifier. +你可以在声明其类型的地方重载下标声明,只要*参数*或*返回类型*与要重载的下标不同。你也可以重写从超类继承的下标声明。在这样做时,必须使用 `override` 声明修饰符标记被重写的下标声明。 -Subscript parameters follow the same rules as function parameters, -with two exceptions. -By default, the parameters used in subscripting don't have argument labels, -unlike functions, methods, and initializers. -However, you can provide explicit argument labels -using the same syntax that functions, methods, and initializers use. -In addition, subscripts can't have in-out parameters. -A subscript parameter can have a default value, -using the syntax described in . +下标参数遵循与函数参数相同的规则,但有两个例外。默认情况下,使用下标的参数没有参数标签,这与函数、方法和构造器不同。然而,你可以使用与函数、方法和构造器相同的语法提供显式参数标签。此外,下标不能有 in-out 参数。下标参数可以具有默认值,参见 。 -You can also declare subscripts in the context of a protocol declaration, -as described in . +你还可以在协议声明的上下文中声明下标,参见 。 -For more information about subscripting and to see examples of subscript declarations, -see . +有关下标的更多信息以及下标声明的示例,请参见 。 -### Type Subscript Declarations +### 类型下标声明 -To declare a subscript that's exposed by the type, -rather than by instances of the type, -mark the subscript declaration with the `static` declaration modifier. -Classes can mark type computed properties with the `class` declaration modifier instead -to allow subclasses to override the superclass’s implementation. -In a class declaration, -the `static` keyword has the same effect as marking the declaration -with both the `class` and `final` declaration modifiers. +要声明由类型本身而非类型实例公开的下标,可以在下标声明中使用 `static` 声明修饰符。类可以使用 `class` 声明修饰符来标记类型计算属性,以允许子类重写超类的实现。在类声明中,`static` 关键字的效果与将声明标记为 `class` 和 `final` 声明修饰符相同。 -> Grammar of a subscript declaration: +> 下标声明的语法: > > *subscript-declaration* → *subscript-head* *subscript-result* *generic-where-clause*_?_ *code-block* \ > *subscript-declaration* → *subscript-head* *subscript-result* *generic-where-clause*_?_ *getter-setter-block* \ @@ -3570,33 +2633,23 @@ with both the `class` and `final` declaration modifiers. > *subscript-head* → *attributes*_?_ *declaration-modifiers*_?_ **`subscript`** *generic-parameter-clause*_?_ *parameter-clause* \ > *subscript-result* → **`->`** *attributes*_?_ *type* -## Macro Declaration +## 宏声明 -A *macro declaration* introduces a new macro. -It begins with the `macro` keyword -and has the following form: +*宏声明*引入一个新的宏。它以 `macro` 关键字开始,具有以下形式: ```swift macro <#name#> = <#macro implementation#> ``` -The *macro implementation* is another macro, -and indicates the location of the code that performs this macro's expansion. -The code that performs macro expansion is a separate Swift program, -that uses the [SwiftSyntax][] module to interact with Swift code. -Call the `externalMacro(module:type:)` macro from the Swift standard library, -passing in the name of a type that contains the macro's implementation, -and the name of the module that contains that type. +*宏实现*是另一个宏,用于指示执行此宏扩展的代码位置。执行宏扩展的代码是一个独立的 Swift 程序,该程序使用 [SwiftSyntax][] 模块与 Swift 代码进行交互。调用 Swift 标准库中的 `externalMacro(module:type:)` 宏,并传入包含宏实现的类型名称以及包含该类型的模块名称。 [SwiftSyntax]: http://github.com/apple/swift-syntax/ -Macros can be overloaded, -following the same model used by functions. -A macro declaration appears only at file scope. +宏可以被重载,遵循与函数相同的模型。宏声明仅在文件作用域内出现。 -For an overview of macros in Swift, see . +有关 Swift 中宏的概述,请参见 。 -> Grammar of a macro declaration: +> 宏声明的语法: > > *macro-declaration* → *macro-head* *identifier* *generic-parameter-clause*_?_ *macro-signature* *macro-definition*_?_ *generic-where-clause* \ > *macro-head* → *attributes*_?_ *declaration-modifiers*_?_ **`macro`** \ @@ -3604,76 +2657,47 @@ For an overview of macros in Swift, see . > *macro-function-signature-result* → **`->`** *type* \ > *macro-definition* → **`=`** *expression* -## Operator Declaration +## 操作符声明 -An *operator declaration* introduces a new infix, prefix, -or postfix operator into your program -and is declared using the `operator` keyword. +*运算符声明*将新的中缀、前缀或后缀运算符引入到你的程序中,并使用 `operator` 关键字进行声明。 -You can declare operators of three different fixities: -infix, prefix, and postfix. -The *fixity* of an operator specifies the relative position of an operator -to its operands. +你可以声明三种不同优先级的运算符:中缀、前缀和后缀。运算符的*优先级*指定了运算符相对于其操作数的相对位置。 -There are three basic forms of an operator declaration, -one for each fixity. -The fixity of the operator is specified by marking the operator declaration with the -`infix`, `prefix`, or `postfix` declaration modifier before the `operator` keyword. -In each form, the name of the operator can contain only the operator characters -defined in . +运算符声明有三种基本形式,每种形式对应一种结合性。运算符的结合性通过在 `operator` 关键字之前标注 `infix`、`prefix` 或 `postfix` 声明修饰符来指定。在每种形式中,运算符的名称只能包含 中定义的运算符字符。 -The following form declares a new infix operator: +以下形式声明了一个新的中缀运算符: ```swift infix operator <#operator name#>: <#precedence group#> ``` -An *infix operator* is a binary operator that's written between its two operands, -such as the familiar addition operator (`+`) in the expression `1 + 2`. +*中缀运算符*是一个二元运算符,它写在两个操作数之间,例如在表达式 `1 + 2` 中熟悉的加法运算符`+`。 -Infix operators can optionally specify a precedence group. -If you omit the precedence group for an operator, -Swift uses the default precedence group, `DefaultPrecedence`, -which specifies a precedence just higher than `TernaryPrecedence`. -For more information, see . +中缀运算符可以选择性地指定优先级组。如果你省略运算符的优先级组,Swift 将使用默认优先级组 `DefaultPrecedence`,该组的优先级仅高于 `TernaryPrecedence`。有关更多信息,请参见 。 -The following form declares a new prefix operator: +以下形式声明了一个新的前缀运算符: ```swift prefix operator <#operator name#> ``` -A *prefix operator* is a unary operator that's written immediately before its operand, -such as the prefix logical NOT operator (`!`) in the expression `!a`. +*前缀运算符*是一种一元运算符,它直接写在操作数之前,例如表达式 `!a` 中的前缀逻辑非运算符(`!`)。 -Prefix operators declarations don't specify a precedence level. -Prefix operators are nonassociative. +前缀运算符声明不指定优先级。前缀运算符是非结合的。 -The following form declares a new postfix operator: +以下形式声明了一个新的后缀运算符: ```swift postfix operator <#operator name#> ``` -A *postfix operator* is a unary operator that's written immediately after its operand, -such as the postfix forced-unwrap operator (`!`) in the expression `a!`. +*后缀运算符*是一种一元运算符,它紧跟在操作数后面,例如在表达式 `a!` 中的后缀强制解包运算符 `!`。 -As with prefix operators, postfix operator declarations don't specify a precedence level. -Postfix operators are nonassociative. +与前缀运算符一样,后缀运算符声明不指定优先级。后缀运算符是非结合的。 -After declaring a new operator, -you implement it by declaring a static method that has the same name as the operator. -The static method is a member of -one of the types whose values the operator takes as an argument --- -for example, an operator that multiplies a `Double` by an `Int` -is implemented as a static method on either the `Double` or `Int` structure. -If you're implementing a prefix or postfix operator, -you must also mark that method declaration with the corresponding `prefix` or `postfix` -declaration modifier. -To see an example of how to create and implement a new operator, -see . +在声明一个新运算符后,你通过声明一个与运算符同名的静态方法来实现它。这个静态方法是运算符作为参数所接受的类型之一的成员——例如,一个将 `Double` 乘以 `Int` 的运算符是作为 `Double` 或 `Int` 结构上的静态方法实现的。如果你在实现前缀或后缀运算符,你还必须在方法声明中标记相应的 `prefix` 或 `postfix` 声明修饰符。要查看如何创建和实现新运算符的示例,请参见 。 -> Grammar of an operator declaration: +> 操作符声明的语法: > > *operator-declaration* → *prefix-operator-declaration* | *postfix-operator-declaration* | *infix-operator-declaration* > @@ -3683,14 +2707,11 @@ see . > > *infix-operator-group* → **`:`** *precedence-group-name* -## Precedence Group Declaration +## 优先级组声明 -A *precedence group declaration* introduces -a new grouping for infix operator precedence into your program. -The precedence of an operator specifies how tightly the operator -binds to its operands, in the absence of grouping parentheses. +*优先级组声明*在程序中引入了一个新的中缀运算符优先级分组。运算符的优先级指定了在没有分组括号的情况下,运算符与其操作数的绑定紧密程度。 -A precedence group declaration has the following form: +优先级组声明具有以下形式: ```swift precedencegroup <#precedence group name#> { @@ -3701,63 +2722,18 @@ precedencegroup <#precedence group name#> { } ``` -The *lower group names* and *higher group names* lists specify -the new precedence group's relation to existing precedence groups. -The `lowerThan` precedence group attribute may only be used -to refer to precedence groups declared outside of the current module. -When two operators compete with each other for their operands, -such as in the expression `2 + 3 * 5`, -the operator with the higher relative precedence -binds more tightly to its operands. - -> Note: Precedence groups related to each other -> using *lower group names* and *higher group names* -> must fit into a single relational hierarchy, -> but they *don't* have to form a linear hierarchy. -> This means it's possible to have precedence groups -> with undefined relative precedence. -> Operators from those precedence groups -> can't be used next to each other without grouping parentheses. - -Swift defines numerous precedence groups to go along -with the operators provided by the Swift standard library. -For example, the addition (`+`) and subtraction (`-`) operators -belong to the `AdditionPrecedence` group, -and the multiplication (`*`) and division (`/`) operators -belong to the `MultiplicationPrecedence` group. -For a complete list of precedence groups -provided by the Swift standard library, -see [Operator Declarations](https://developer.apple.com/documentation/swift/operator_declarations). - -The *associativity* of an operator specifies how a sequence of operators -with the same precedence level are grouped together in the absence of grouping parentheses. -You specify the associativity of an operator by writing -one of the context-sensitive keywords `left`, `right`, or `none` --- -if your omit the associativity, the default is `none`. -Operators that are left-associative group left-to-right. -For example, -the subtraction operator (`-`) is left-associative, -so the expression `4 - 5 - 6` is grouped as `(4 - 5) - 6` -and evaluates to `-7`. -Operators that are right-associative group right-to-left, -and operators that are specified with an associativity of `none` -don't associate at all. -Nonassociative operators of the same precedence level -can't appear adjacent to each to other. -For example, -the `<` operator has an associativity of `none`, -which means `1 < 2 < 3` isn't a valid expression. - -The *assignment* of a precedence group specifies the precedence of an operator -when used in an operation that includes optional chaining. -When set to `true`, an operator in the corresponding precedence group -uses the same grouping rules during optional chaining -as the assignment operators from the Swift standard library. -Otherwise, when set to `false` or omitted, -operators in the precedence group follows the same optional chaining rules -as operators that don't perform assignment. - -> Grammar of a precedence group declaration: +*低级组名称*和*高级组名称*列表指定了新优先级组与现有优先级组的关系。`lowerThan` 优先级组属性只能用于引用当前模块外声明的优先级组。当两个运算符争夺其操作数时,如在表达式 `2 + 3 * 5` 中,具有较高相对优先级的运算符会更紧密地绑定到其操作数上。 + +> 注意: +> 使用*低级组名称*和*高级组名称*相关联的优先级组必须适合于单一的关系层次结构,但它们*不*必形成线性层次结构。这意味着可以有相对优先级未定义的优先级组。来自这些优先级组的运算符不能在没有分组括号的情况下相互使用。 + +Swift 定义了许多优先级组,以配合 Swift 标准库提供的运算符。例如,加法 (`+`) 和减法 (`-`) 运算符属于 `AdditionPrecedence` 组,而乘法 (`*`) 和除法 (`/`) 运算符属于 `MultiplicationPrecedence` 组。有关 Swift 标准库提供的优先级组的完整列表,请参见[运算符声明](https://developer.apple.com/documentation/swift/operator_declarations)。 + +运算符的*结合性*指定了在没有分组括号的情况下,具有相同优先级的运算符序列是如何分组的。通过写入上下文敏感的关键字之一来指定运算符的结合性:`left`、`right` 或 `none` ——如果你省略结合性,默认值为 `none`。左结合的运算符从左到右分组。例如,减法运算符(`-`)是左结合的,因此表达式`4 - 5 - 6` 被分组为 `(4 - 5) - 6`,并计算为 `-7`。右结合的运算符从右到左分组,而指定为 `none` 的运算符则完全不结合。相同优先级的非结合运算符不能相邻出现。例如,`<` 运算符的结合性为 `none`,这意味着 `1 < 2 < 3` 不是一个有效的表达式。 + +*赋值*优先级组的设置指定了运算符在包含可选链操作中的优先级。当设置为 `true` 时,对应优先级组中的运算符在可选链操作期间使用与 Swift 标准库中的赋值运算符相同的分组规则。否则,当设置为 `false` 或省略时,该优先级组中的运算符将遵循与不执行赋值的运算符相同的可选链规则。 + +> 优先级组声明的语法: > > *precedence-group-declaration* → **`precedencegroup`** *precedence-group-name* **`{`** *precedence-group-attributes*_?_ **`}`** > @@ -3778,58 +2754,23 @@ as operators that don't perform assignment. > *precedence-group-names* → *precedence-group-name* | *precedence-group-name* **`,`** *precedence-group-names* \ > *precedence-group-name* → *identifier* -## Declaration Modifiers - -*Declaration modifiers* are keywords or context-sensitive keywords that modify the behavior -or meaning of a declaration. You specify a declaration modifier by writing the appropriate -keyword or context-sensitive keyword between a declaration's attributes (if any) and the keyword -that introduces the declaration. - -- term `class`: - Apply this modifier to a member of a class - to indicate that the member is a member of the class itself, - rather than a member of instances of the class. - Members of a superclass that have this modifier - and don't have the `final` modifier - can be overridden by subclasses. - -- term `dynamic`: - Apply this modifier to any member of a class that can be represented by Objective-C. - When you mark a member declaration with the `dynamic` modifier, - access to that member is always dynamically dispatched using the Objective-C runtime. - Access to that member is never inlined or devirtualized by the compiler. - - Because declarations marked with the `dynamic` modifier are dispatched - using the Objective-C runtime, they must be marked with the - `objc` attribute. - -- term `final`: - Apply this modifier to a class or to a property, method, - or subscript member of a class. It's applied to a class to indicate that the class - can't be subclassed. It's applied to a property, method, or subscript of a class - to indicate that a class member can't be overridden in any subclass. - For an example of how to use the `final` attribute, - see . - -- term `lazy`: - Apply this modifier to a stored variable property of a class or structure - to indicate that the property's initial value is calculated and stored at most - once, when the property is first accessed. - For an example of how to use the `lazy` modifier, - see . - -- term `optional`: - Apply this modifier to a protocol's property, method, - or subscript members to indicate that a conforming type isn't required - to implement those members. - - You can apply the `optional` modifier only to protocols that are marked - with the `objc` attribute. As a result, only class types can adopt and conform - to a protocol that contains optional member requirements. - For more information about how to use the `optional` modifier - and for guidance about how to access optional protocol members --- - for example, when you're not sure whether a conforming type implements them --- - see . +## 声明修饰符 + +*声明修饰符* 是用于修改声明行为或意义的关键字或上下文相关关键字。你通过在声明的属性(如果有的话)和引入声明的关键字之间写入相应的关键字或上下文相关关键字来指定声明修饰符。 + +- `class`:将此修饰符应用于类的成员,以指示该成员是类本身的成员,而不是类实例的成员。具有此修饰符且没有 `final` 修饰符的超类成员可以被子类重写。 + +- `dynamic`:将此修饰符应用于可以用 Objective-C 表示的类的任何成员。当你使用 `dynamic` 修饰符标记成员声明时,对该成员的访问始终通过 Objective-C 运行时动态分派。对该成员的访问永远不会被编译器内联或去虚拟化。 + +因为带有 `dynamic` 修饰符的声明是通过 Objective-C 运行时进行调度的,因此它们必须标记为 `objc` 属性。 + +- `final`:将此修饰符应用于类或类的属性、方法或下标成员。它应用于类以指示该类不能被子类化。它应用于类的属性、方法或下标,以指示类成员在任何子类中不能被重写。有关如何使用 `final` 属性的示例,请参见 。 + +- `lazy`:将此修饰符应用于类或结构体的存储变量属性,以指示该属性的初始值在第一次访问该属性时最多计算并存储一次。有关如何使用 `lazy` 修饰符的示例,请参见 。 + +- `optional`:将此修饰符应用于协议的属性、方法或下标成员,表示实现该协议的类型不必实现这些成员。 + +你只能将 `optional` 修饰符应用于带有 `objc` 属性的协议。因此,只有类类型可以采用并遵循包含可选成员要求的协议。有关如何使用 `optional` 修饰符的更多信息,以及在不确定遵循类型是否实现了这些成员时如何访问可选协议成员的指导,请参见 -- term `required`: - Apply this modifier to a designated or convenience initializer - of a class to indicate that every subclass must implement that initializer. - The subclass's implementation of that initializer - must also be marked with the `required` modifier. - -- term `static`: - Apply this modifier to a member of a structure, class, enumeration, or protocol - to indicate that the member is a member of the type, - rather than a member of instances of that type. - In the scope of a class declaration, - writing the `static` modifier on a member declaration - has the same effect as writing the `class` and `final` modifiers - on that member declaration. - However, constant type properties of a class are an exception: - `static` has its normal, nonclass meaning there - because you can't write `class` or `final` on those declarations. - -- term `unowned`: - Apply this modifier to a stored variable, constant, or stored property - to indicate that the variable or property has an unowned reference - to the object stored as its value. - If you try to access the variable or property - after the object has been deallocated, - a runtime error is raised. - Like a weak reference, - the type of the property or value must be a class type; - unlike a weak reference, - the type is non-optional. - For an example and more information about the `unowned` modifier, - see . - -- term `unowned(safe)`: - An explicit spelling of `unowned`. - -- term `unowned(unsafe)`: - Apply this modifier to a stored variable, constant, or stored property - to indicate that the variable or property has an unowned reference - to the object stored as its value. - If you try to access the variable or property - after the object has been deallocated, - you'll access the memory at the location where the object used to be, - which is a memory-unsafe operation. - Like a weak reference, - the type of the property or value must be a class type; - unlike a weak reference, - the type is non-optional. - For an example and more information about the `unowned` modifier, - see . - -- term `weak`: - Apply this modifier to a stored variable or stored variable property - to indicate that the variable or property has a weak reference to the - object stored as its value. The type of the variable or property - must be an optional class type. - If you access the variable or property - after the object has been deallocated, - its value is `nil`. - For an example and more information about the `weak` modifier, - see . - -### Access Control Levels - -Swift provides five levels of access control: open, public, internal, file private, and private. -You can mark a declaration with one of the access-level modifiers below -to specify the declaration's access level. -Access control is discussed in detail in . - -- term `open`: - Apply this modifier to a declaration to indicate the declaration can be accessed and subclassed - by code in the same module as the declaration. - Declarations marked with the `open` access-level modifier can also be accessed and subclassed - by code in a module that imports the module that contains that declaration. - -- term `public`: - Apply this modifier to a declaration to indicate the declaration can be accessed and subclassed - by code in the same module as the declaration. - Declarations marked with the `public` access-level modifier can also be accessed (but not subclassed) - by code in a module that imports the module that contains that declaration. - -- term `package`: - Apply this modifier to a declaration - to indicate that the declaration can be accessed - only by code in the same package as the declaration. - A package is a unit of code distribution - that you define in the build system you're using. - When the build system compiles code, - it specifies the package name - by passing the `-package-name` flag to the Swift compiler. - Two modules are part of the same package - if the build system specifies the same package name when building them. - -- term `internal`: - Apply this modifier to a declaration to indicate the declaration can be accessed - only by code in the same module as the declaration. - By default, - most declarations are implicitly marked with the `internal` access-level modifier. - -- term `fileprivate`: - Apply this modifier to a declaration to indicate the declaration can be accessed - only by code in the same source file as the declaration. - -- term `private`: - Apply this modifier to a declaration to indicate the declaration can be accessed - only by code within the declaration's immediate enclosing scope. - -For the purpose of access control, -extensions behave as follows: - -- If there are multiple extensions in the same file, - and those extensions all extend the same type, - then all of those extensions have the same access-control scope. - The extensions and the type they extend can be in different files. - -- If there are extensions in the same file as the type they extend, - the extensions have the same access-control scope as the type they extend. - -- Private members declared in a type's declaration - can be accessed from extensions to that type. - Private members declared in one extension - can be accessed from other extensions - and from the extended type's declaration. - -Each access-level modifier above optionally accepts a single argument, -which consists of the `set` keyword enclosed in parentheses --- -for example, `private(set)`. -Use this form of an access-level modifier when you want to specify an access level -for the setter of a variable or subscript that's less than or equal -to the access level of the variable or subscript itself, -as discussed in . - -> Grammar of a declaration modifier: +- `required`:将此修饰符应用于类的指定或便利构造器,以指示每个子类必须实现该构造器。子类对该构造器的实现也必须标记为 `required` 修饰符。 + +- `static`:将此修饰符应用于结构体、类、枚举或协议的成员,以指示该成员属于类型本身,而不是该类型实例的成员。在类声明的作用域内,将 `static` 修饰符应用于成员声明上,与在该成员声明上写 `class` 和 `final` 修饰符具有相同的效果。然而,类的常量类型属性是一个例外:在这种情况下,`static` 具有其通常的、非类相关的含义,因为在这些声明上不能使用 `class` 或 `final`。 + +- `unowned`:将此修饰符应用于存储变量、常量或存储属性,以指示该变量或属性对作为其值存储的对象具有一个无主引用。如果在对象被释放后尝试访问该变量或属性,将会引发运行时错误。与弱引用类似,属性或值的类型必须是类类型;与弱引用不同,类型是非可选的。有关 `unowned` 修饰符的示例和更多信息,请参见 。 + +- `unowned(safe)`:`unowned` 的显式拼写。 + +- `unowned(unsafe)`:将此修饰符应用于存储变量、常量或存储属性,以指示该变量或属性对作为其值存储的对象具有一个无主引用。如果在对象被释放后尝试访问该变量或属性,你将访问对象曾经所在位置的内存,这是一种不安全的内存操作。与弱引用类似,属性或值的类型必须是类类型;与弱引用不同,该类型是非可选的。有关 `unowned` 修饰符的示例和更多信息,请参见 。 + +- `weak`:将此修饰符应用于存储变量或存储变量属性,以指示该变量或属性对作为其值存储的对象具有弱引用。变量或属性的类型必须是可选类类型。如果在对象被释放后访问该变量或属性,其值为 `nil`。有关 `weak` 修饰符的示例和更多信息,请参见 。 + +### 访问控制级别 + +Swift 提供五种访问控制级别:open、public、internal、file private 和 private。你可以使用以下访问级别修饰符之一标记声明,以指定声明的访问级别。访问控制的详细信息请参见 。 + +- `open`:将此修饰符应用于声明,以指示该声明可以被与该声明位于同一模块中的代码访问和子类化。标记为 `open` 访问级别修饰符的声明也可以被导入包含该声明的模块的模块中的代码访问和子类化。 + +- `public`:将此修饰符应用于声明,以指示该声明可以被与该声明位于同一模块中的代码访问和子类化。标记为 `public` 访问级别修饰符的声明也可以被导入包含该声明的模块的模块中的代码访问(但不能被子类化)。 + +- `package`:将此修饰符应用于声明,以指示该声明只能被与声明在同一包中的代码访问。包是你在使用的构建系统中定义的代码分发单元。当构建系统编译代码时,它通过将 `-package-name` 标志传递给 Swift 编译器来指定包名称。如果构建系统在构建它们时指定相同的包名称,则两个模块属于同一个包。 + +- `internal`:将此修饰符应用于声明,以指示该声明只能被与声明在同一模块中的代码访问。默认情况下,大多数声明隐式标记为 `internal` 访问级别修饰符。 + +- `fileprivate`:将此修饰符应用于声明,以指示该声明只能被与声明在同一源文件中的代码访问。 + +- `private`:将此修饰符应用于声明,以指示该声明只能被声明的直接封闭作用域内的代码访问。 + +出于访问控制的目的,扩展的行为如下: + +- 如果同一个文件中有多个扩展,并且这些扩展都扩展了相同的类型,那么所有这些扩展具有相同的访问控制作用域。这些扩展和它们扩展的类型可以在不同的文件中。 + +- 如果扩展与其扩展的类型在同一文件中,则扩展具有与其扩展的类型相同的访问控制作用域。 + +- 在类型声明中声明的私有成员可以从该类型的扩展中访问。在一个扩展中声明的私有成员可以从其他扩展和扩展类型的声明中访问。 + +每个上述访问级别修饰符可选择性地接受一个参数,该参数由括号中包含的 `set` 关键字组成——例如,`private(set)`。当你想要为变量或下标的setter指定一个小于或等于变量或下标本身的访问级别时,请使用这种形式的访问级别修饰符,如 中所讨论的。 + +> 声明修饰语的语法: > > *declaration-modifier* → **`class`** | **`convenience`** | **`dynamic`** | **`final`** | **`infix`** | **`lazy`** | **`optional`** | **`override`** | **`postfix`** | **`prefix`** | **`required`** | **`static`** | **`unowned`** | **`unowned`** **`(`** **`safe`** **`)`** | **`unowned`** **`(`** **`unsafe`** **`)`** | **`weak`** \ > *declaration-modifier* → *access-level-modifier* \ @@ -3989,11 +2837,11 @@ as discussed in . > > *actor-isolation-modifier* → **`nonisolated`** -> Beta Software: +> 测试版软件: > -> This documentation contains preliminary information about an API or technology in development. This information is subject to change, and software implemented according to this documentation should be tested with final operating system software. +> 本文件包含有关正在开发的 API 或技术的初步信息。此信息可能会更改,按照本文件实施的软件应与最终操作系统软件进行测试。 > -> Learn more about using [Apple's beta software](https://developer.apple.com/support/beta-software/). +> 了解有关使用 [Apple 测试版软件](https://developer.apple.com/support/beta-software/) 的更多信息。