在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 一个声明引入了一个新的名称或构建到你的程序。例如,您使用声明来引入函数和方法,引入变量和常量,以及定义枚举,结构,类和协议类型。您还可以使用声明来扩展现有命名类型的行为,并将符号导入到其他地方声明的程序中。 在Swift中,大多数声明也是定义,因为它们是在声明它们的同时实现或初始化的。也就是说,由于协议不实现其成员,因此大多数协议成员仅是声明。为方便起见,因为在Swift中区别并不重要,术语声明包括声明和定义。 1 GRAMMAR OF A DECLARATION 2 3 declaration → import-declaration 4 5 declaration → constant-declaration 6 7 declaration → variable-declaration 8 9 declaration → typealias-declaration 10 11 declaration → function-declaration 12 13 declaration → enum-declaration 14 15 declaration → struct-declaration 16 17 declaration → class-declaration 18 19 declaration → protocol-declaration 20 21 declaration → initializer-declaration 22 23 declaration → deinitializer-declaration 24 25 declaration → extension-declaration 26 27 declaration → subscript-declaration 28 29 declaration → operator-declaration 30 31 declaration → precedence-group-declaration 32 33 declarations → declaration declarations opt 顶级代码Swift源文件中的顶级代码由零个或多个语句,声明和表达式组成。默认情况下,属于同一模块的每个源文件中的代码都可以访问在源文件顶层声明的变量,常量和其他命名声明。您可以通过使用访问级别修饰符标记声明来覆盖此默认行为,如访问控制级别中所述。 1 GRAMMAR OF A TOP-LEVEL DECLARATION 2 3 top-level-declaration → statements opt 代码块甲码块是由各种声明和控制结构,以组语句一起使用。它具有以下形式: 1 { 2 statements 3 } 代码块中的语句包括声明,表达式和其他类型的语句,并按照它们在源代码中的出现顺序执行。 1 GRAMMAR OF A CODE BLOCK 2 3 code-block → { statements opt } 引用声明一个引用声明,您可以访问声明当前文件之外的符号。基本表单导入整个模块; 它由 import module 提供更多详细信息限制导入的符号 - 您可以在模块或子模块中指定特定子模块或特定声明。使用此详细表单时,只有导入的符号(而不是声明它的模块)在当前作用域中可用。 1 import import kind module.symbol name 2 import module.submodule 1 GRAMMAR OF AN IMPORT DECLARATION 2 3 import-declaration → attributes opt import import-kind opt import-path 4 5 import-kind → typealias | struct | class | enum | protocol | let | var | func 6 7 import-path → import-path-identifier | import-path-identifier . import-path 8 9 import-path-identifier → identifier | operator 常数声明一个常数声明引入了一个名为常量的值到你的程序。使用 let constant name: type = expression 常量声明定义常量名称和初始化表达式值之间的不可变绑定; 设置常量值后,不能更改。也就是说,如果使用类对象初始化常量,则对象本身可以更改,但常量名称与其引用的对象之间的绑定不能。 当在全局范围内声明常量时,必须使用值初始化它。当在函数或方法的上下文中发生常量声明时,可以稍后对其进行初始化,只要保证在第一次读取其值之前设置值即可。当在类或结构声明的上下文中发生常量声明时,它被视为常量属性。常量声明不是计算属性,因此没有getter或setter。 如果常量声明的常量名称是元组模式,则元组中每个项的名称将绑定到初始化表达式中的相应值。 let (firstNumber, secondNumber) = (10, 42) 在此示例中, 1 print("The first number is \(firstNumber).") 2 // Prints "The first number is 10." 3 print("The second number is \(secondNumber).") 4 // Prints "The second number is 42." 当可以推断常量名称的类型时,类型注释( 要声明常量类型属性,请使用 有关常量的更多信息以及有关何时使用它们的指导,请参阅常量和变量以及存储的属性。 1 GRAMMAR OF A CONSTANT DECLARATION 2 3 constant-declaration → attributes opt declaration-modifiers opt let pattern-initializer-list 4 5 pattern-initializer-list → pattern-initializer | pattern-initializer , pattern-initializer-list 6 7 pattern-initializer → pattern initializer opt 8 9 initializer → = expression 变量声明一个变量声明引入了一个名为变量值到你的程序,并使用声明 变量声明有几种形式,用于声明不同类型的命名可变值,包括存储和计算变量和属性,存储变量和属性观察器以及静态变量属性。要使用的适当形式取决于声明变量的范围以及要声明的变量类型。 注意 您还可以在协议声明的上下文中声明属性,如协议属性声明中所述。 您可以通过使用 存储变量和存储变量属性以下表单声明存储变量或存储变量属性: var variable name: type = expression
您可以在全局范围,函数的本地范围或类或结构声明的上下文中定义此形式的变量声明。当在全局范围或函数的局部范围声明此表单的变量声明时,它被称为存储变量。当它在类或结构声明的上下文中声明时,它被称为存储变量属性。 初始化表达式不能出现在协议声明中,但在所有其他上下文中,初始化表达式是可选的。也就是说,如果不存在初始化表达式,则变量声明必须包含显式类型注释( 与常量声明一样,如果变量名是元组模式,则元组中每个项的名称将绑定到初始化表达式中的相应值。 顾名思义,存储变量或存储变量属性的值存储在内存中。 计算变量和计算属性以下表单声明计算变量或计算属性: 1 var variable name: type { 2 get { 3 statements 4 } 5 set(setter name) { 6 statements 7 } 8 } 您可以在全局范围,函数的本地范围或类,结构,枚举或扩展声明的上下文中定义此形式的变量声明。当在全局范围或函数的局部范围声明此形式的变量声明时,它被称为计算变量。当它在类,结构或扩展声明的上下文中声明时,它被称为计算属性。 getter用于读取值,setter用于写入值。setter子句是可选的,当只需要一个getter时,你可以省略这两个子句,直接返回所请求的值,如Read-Only Computed Properties中所述。但是,如果提供setter子句,则还必须提供getter子句。 该二传手名称和圆括号是可选的。如果提供setter名称,则将其用作setter参数的名称。如果未提供setter名称,则seter的默认参数名称为 与存储的命名值和存储的变量属性不同,计算的命名值或计算属性的值不存储在内存中。 有关更多信息以及查看计算属性的示例,请参阅计算属性。 存储变量观察器和属性观察器您还可以使用 1 var variable name: type = expression { 2 willSet(setter name) { 3 statements 4 } 5 didSet(setter name) { 6 statements 7 } 8 } 您可以在全局范围,函数的本地范围或类或结构声明的上下文中定义此形式的变量声明。当在全局范围或函数的局部范围声明此表单的变量声明时,观察器称为存储变量观察器。当在类或结构声明的上下文中声明它时,观察器被称为属性观察器。 您可以将属性观察器添加到任何存储的属性。您还可以通过覆盖子类中的属性将属性观察器添加到任何继承的属性(无论是存储还是计算),如覆盖属性观察器中所述。 初始化表达式在类或结构声明的上下文中是可选的,但在其他地方需要。该类型的注释是可选的,当类型可以从初始化推断表达。 的 一个 和子句中的setter名称和括号是可选的。如果提供setter名称,它们将用作和观察器的参数名称。如果不提供setter名称,则观察器的默认参数名称为观察器的默认参数名称。
有关更多信息以及查看如何使用属性观察器的示例,请参阅Property Observers。 变量属性要声明类型变量属性,请使用 注意 在类声明中, 1 GRAMMAR OF A VARIABLE DECLARATION 2 3 variable-declaration → variable-declaration-head pattern-initializer-list 4 5 variable-declaration → variable-declaration-head variable-name type-annotation code-block 6 7 variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-block 8 9 variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-keyword-block 10 11 variable-declaration → variable-declaration-head variable-name initializer willSet-didSet-block 12 13 variable-declaration → variable-declaration-head variable-name type-annotation initializer opt willSet-didSet-block 14 15 variable-declaration-head → attributes opt declaration-modifiers opt var 16 17 variable-name → identifier 18 19 getter-setter-block → code-block 20 21 getter-setter-block → { getter-clause setter-clause opt } 22 23 getter-setter-block → { setter-clause getter-clause } 24 25 getter-clause → attributes opt mutation-modifier opt get code-block 26 27 setter-clause → attributes opt mutation-modifier opt set setter-name opt code-block 28 29 setter-name → ( identifier ) 30 31 getter-setter-keyword-block → { getter-keyword-clause setter-keyword-clause opt } 32 33 getter-setter-keyword-block → { setter-keyword-clause getter-keyword-clause } 34 35 getter-keyword-clause → attributes opt mutation-modifier opt get 36 37 setter-keyword-clause → attributes opt mutation-modifier opt set 38 39 willSet-didSet-block → { willSet-clause didSet-clause opt } 40 41 willSet-didSet-block → { didSet-clause willSet-clause opt } 42 43 willSet-clause → attributes opt willSet setter-name opt code-block 44 45 didSet-clause → attributes opt didSet setter-name opt code-block 类型别名声明一个类型别名声明介绍了现有类型的命名别名到你的程序。类型别名声明使用 typealias name = existing type 一个类型别名声明后,别名名称可以代替的现有类型无处不在你的程序。在现有类型可以是命名型或复合型。类型别名不会创建新类型; 它们只是允许名称引用现有类型。 类型别名声明可以使用泛型参数为现有泛型类型指定名称。类型别名可以为现有类型的部分或全部通用参数提供具体类型。例如: 1 typealias StringDictionary<Value> = Dictionary<String, Value> 2 3 // The following dictionaries have the same type. 4 var dictionary1: StringDictionary<Int> = [:] 5 var dictionary2: Dictionary<String, Int> = [:] 当使用泛型参数声明类型别名时,对这些参数的约束必须与现有类型的泛型参数的约束完全匹配。例如: typealias DictionaryOfInts<Key: Hashable> = Dictionary<Key, Int> 由于类型别名和现有类型可以互换使用,因此类型别名不能引入其他通用约束。 类型别名可以通过省略声明中的所有泛型参数来转发现有类型的泛型参数。例如, typealias Diccionario = Dictionary 在协议声明中,类型别名可以为经常使用的类型提供更简单,更方便的名称。例如: 1 protocol Sequence { 2 associatedtype Iterator: IteratorProtocol 3 typealias Element = Iterator.Element 4 } 5 6 func sum<T: Sequence>(_ sequence: T) -> Int where T.Element == Int { 7 // ... 8 } 如果没有此类别别名,则该 另请参阅协议关联类型声明。 1 GRAMMAR OF A TYPE ALIAS DECLARATION 2 3 typealias-declaration → attributes opt access-level-modifier opt typealias typealias-name generic-parameter-clause opt typealias-assignment 4 5 typealias-name → identifier 6 7 typealias-assignment → = type 函数声明一个函数声明引入了一个函数或方法到你的程序。在类,结构,枚举或协议的上下文中声明的函数称为方法。函数声明使用 1 func function name(parameters) -> return type { 2 statements 3 } 如果函数的返回类型为 1 func function name(parameters) { 2 statements 3 } 必须包含每个参数的类型 - 无法推断。如果 函数可以使用元组类型作为函数的返回类型返回多个值。 函数定义可以出现在另一个函数声明中。这种函数称为嵌套函数。 如果嵌套函数捕获保证永不转义的值(例如输入输出参数)或作为非转义函数参数传递,则嵌套函数是非转义的。否则,嵌套函数是一个转义函数。 有关嵌套函数的讨论,请参阅嵌套函数。 参数名称函数参数是以逗号分隔的列表,其中每个参数都具有多种形式之一。函数调用中参数的顺序必须与函数声明中的参数顺序相匹配。参数列表中最简单的条目具有以下形式: parameter name: parameter type 参数具有在函数体中使用的名称,以及在调用函数或方法时使用的参数标签。默认情况下,参数名称也用作参数标签。例如: 1 func f(x: Int, y: Int) -> Int { return x + y } 2 f(x: 1, y: 2) // both x and y are labeled 您可以使用以下格式之一覆盖参数标签的默认行为: 1 argument label parameter name: parameter type 2 _ parameter name: parameter type 参数名称前面的名称为参数提供显式参数标签,该标签可以与参数名称不同。相应的参数必须在函数或方法调用中使用给定的参数标签。
1 func repeatGreeting(_ greeting: String, count n: Int) { /* Greet n times */ } 2 repeatGreeting("Hello, world!", count: 2) // count is labeled, greeting is not 输入输出参数输入输出参数传递如下:
此行为称为copy-in copy-out或按值调用结果。例如,当计算属性或具有观察器的属性作为输入输出参数传递时,其getter作为函数调用的一部分被调用,其setter作为函数返回的一部分被调用。 作为优化,当参数是存储在存储器中的物理地址处的值时,在函数体内部和外部使用相同的存储器位置。优化的行为称为引用调用 ; 它满足了拷入式拷贝模型的所有要求,同时消除了复制的开销。使用copy-in copy-out给出的模型编写代码,而不依赖于逐个引用的优化,以便在有或没有优化的情况下它的行为正确。 在函数内,不要访问作为输入输出参数传递的值,即使原始值在当前范围内可用。访问原始版本是同时访问该值,这违反了Swift的内存独占性保证。出于同样的原因,您无法将相同的值传递给多个输入输出参数。 有关内存安全性和内存独占性的更多信息,请参阅内存安全性。 捕获输入输出参数的闭包或嵌套函数必须是非溢出的。如果您需要捕获in-out参数而不进行变更或观察其他代码所做的更改,请使用捕获列表以不可变的方式显式捕获参数。 1 func someFunction(a: inout Int) -> () -> Int { 2 return { [a] in return a + 1 } 3 } 如果需要捕获并改变输入输出参数,请使用显式本地副本,例如在多线程代码中确保在函数返回之前完成所有变异。 1 func multithreadedFunction(queue: DispatchQueue, x: inout Int) { 2 // Make a local copy and manually copy it back. 3 var localX = x 4 defer { x = localX } 5 6 // Operate on localX asynchronously, then wait before returning. 7 queue.async { someMutatingOperation(&localX) } 8 queue.sync {} 9 } 有关输入输出参数的更多讨论和示例,请参阅输入输出参数。 特殊参数可以忽略参数,获取可变数量的值,并使用以下形式提供默认值: 1 _ : parameter type 2 parameter name: parameter type... 3 parameter name: parameter type = default argument value 下划线( 具有基本类型名称后面紧跟三个点( 具有等号( 1 func f(x: Int = 42) -> Int { return x } 2 f() // Valid, uses default value 3 f(x: 7) // Valid, uses the value provided 4 f(7) // Invalid, missing argument label 特殊方法枚举或修改的结构上的方法 必须使用 与类型而不是类型实例关联的方法必须使用 投掷功能和方法必须使用 1 func function name(parameters) throws -> return type { 2 statements 3 } 对throw函数或方法的调用必须包装在一个 该 您不能仅基于函数是否可以引发错误来重载函数。也就是说,您可以根据函数参数是否可以引发错误来重载函数。 投掷方法不能覆盖非投掷方法,投掷方法不能满足非投掷方法的协议要求。也就是说,非投掷方法可以覆盖投掷方法,非投掷方法可以满足投掷方法的协议要求。 重新定义函数和方法可以使用 1 func someFunction(callback: () throws -> Void) rethrows { 2 try callback() 3 } 重新抛出函数或方法 1 func alwaysThrows() throws { 2 throw SomeError.error 3 } 4 func someFunction(callback: () throws -> Void) rethrows { 5 do { 6 try callback() 7 try alwaysThrows() // Invalid, alwaysThrows() isn't a throwing parameter 8 } catch { 9 throw AnotherError.error 10 } 11 } 投掷方法不能覆盖重新抛出方法,投掷方法不能满足重新抛出方法的协议要求。也就是说,重新抛出方法可以覆盖投掷方法,并且重新抛出方法可以满足投掷方法的协议要求。 非返回的功能Swift定义了一个 可以调用非返回函数或方法来结束 您可以覆盖非返回方法,但新方法必须保留其返回类型和非返回行为。 1 GRAMMAR OF A FUNCTION DECLARATION 2 3 function-declaration → function-head function-name generic-parameter-clause opt function-signature generic-where-clause opt function-body opt 4 5 function-head → attributes opt declaration-modifiers opt func 6 7 function-name → identifier | operator 8 9 function-signature → parameter-clause throwsopt function-result opt 10 11 function-signature → parameter-clause rethrows function-result opt 12 13 function-result → -> attributes opt type 14 15 function-body → code-block 16 17 parameter-clause → ( ) | ( parameter-list ) 18 19 parameter-list → parameter | parameter , parameter-list 20 21 parameter → external-parameter-name opt local-parameter-name type-annotation default-argument-clause opt 22 23 parameter → external-parameter-name opt local-parameter-name type-annotation 24 25 parameter → external-parameter-name opt local-parameter-name type-annotation ... 26 27 external-parameter-name → identifier 28 29 local-parameter-name → identifier 30 31 default-argument-clause → = expression 枚举声明一个枚举声明引入了一个名为枚举类型到你的程序。 枚举声明有两种基本形式,并使用 枚举类型可以采用任意数量的协议,但不能从类,结构或其他枚举继承。 与类和结构不同,枚举类型没有隐式提供的默认初始值设定项; 必须明确声明所有初始值设定项。初始化程序可以委托给枚举中的其他初始化程序,但只有在初始化程序将其中一个枚举情况分配给初始化程序后,初始化过程才会完成 与结构类似,但与类不同,枚举是值类型; 枚举的实例在分配给变量或常量时复制,或者作为参数传递给函数调用时复制。有关值类型的信息,请参阅结构和枚举是值类型。 您可以使用扩展声明扩展枚举类型的行为,如扩展声明中所述。 任何类型的枚举个案以下表单声明了一个枚举类型,其中包含任何类型的枚举个案: 1 enum enumeration name: adopted protocols { 2 case enumeration case 1 3 case enumeration case 2(associated value types) 4 } 以这种形式声明的枚举有时被称为其他编程语言中的歧视联合。 在此表单中,每个案例块由 存储关联值的枚举情况可用作创建具有指定关联值的枚举实例的函数。就像函数一样,您可以获得对枚举案例的引用,并在稍后的代码中应用它。 1 enum Number { 2 case integer(Int) 3 case real(Double) 4 } 5 let f = Number.integer 6 // f is a function of type (Int) -> Number 7 8 // Apply f to create an array of Number instances with integer values 9 let evenInts: [Number] = [0, 2, 4, 6].map(f) 有关更多信息以及查看具有关联值类型的案例示例,请参阅关联值。 具有间接的枚举枚举可以具有递归结构,也就是说,它们可以具有关联值的案例,这些值是枚举类型本身的实例。但是,枚举类型的实例具有值语义,这意味着它们在内存中具有固定的布局。为了支持递归,编译器必须插入一个间接层。 要为特定枚举情况启用间接寻址,请使用 1 enum Tree<T> { 2 case empty 3 indirect case node(value: T, left: Tree, right: Tree) 4 } 要为具有关联值的枚举的所有情况启用间接,请使用 使用 有关原始价值案件的查点以下表单声明一个枚举类型,其中包含相同基本类型的枚举个案: 1 enum enumeration name: raw-value type, adopted protocols { 2 case enumeration case 1 = raw value 1 3 case enumeration case 2 = raw value 2 4 } 在此表单中,每个案例块由 如果原始值的类型被指定为 1 enum ExampleEnum: Int { 2 case a, b, c = 5, d 3 } 在上面的例子中,原始值 如果将原始值类型指定为 1 enum GamePlayMode: String { 2 case cooperative, individual, competitive 3 } 在上面的例子中,原始值 具有原始值类型的枚举隐式地符合 |
请发表评论