在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 在Swift中,有两种类型:命名类型和复合类型。一个名为类型是当它的定义可以给出一个特定名称的类型。命名类型包括类,结构,枚举和协议。例如,名为的用户定义类的实例 通常在其他语言中被认为是基本或原始的数据类型(例如表示数字,字符和字符串的类型)实际上是命名类型,使用结构在Swift标准库中定义和实现。因为它们是命名类型,所以您可以使用“ 扩展和扩展声明”中讨论的扩展声明来扩展其行为以满足程序的需要。 阿化合物类型是没有名字的类型,在夫特语言本身定义的。有两种复合类型:函数类型和元组类型。复合类型可以包含命名类型和其他复合类型。例如,元组类型包含两个元素:第一个是命名类型,第二个是另一个复合类型。 您可以在命名类型或复合类型周围放置括号。但是,在类型周围添加括号不会产生任何影响。例如, 本章讨论Swift语言本身定义的类型,并描述Swift的类型推断行为。 一种类型的语法 1 GRAMMAR OF A TYPE 2 3 type → array-type 4 5 type → dictionary-type 6 7 type → function-type 8 9 type → type-identifier 10 11 type → tuple-type 12 13 type → optional-type 14 15 type → implicitly-unwrapped-optional-type 16 17 type → protocol-composition-type 18 19 type → metatype-type 20 21 type → Any 22 23 type → Self 24 25 type → ( type ) 类型注释类型标注明确指定的变量或表达式的类型。类型注释以冒号( 1 let someTuple: (Double, Double) = (3.14159, 2.71828) 2 func someFunction(a: Int) { /* ... */ } 在第一个示例中,表达式 类型注释可以在类型之前包含类型属性的可选列表。 1 GRAMMAR OF A TYPE ANNOTATION 2 3 type-annotation → : attributes opt inoutopt type 类型标识符类型标识符指的是命名类型或命名类型或复合类型的类型别名。 大多数情况下,类型标识符直接引用与标识符同名的命名类型。例如, 有两种情况,类型标识符不引用具有相同名称的类型。在第一种情况下,类型标识符指的是命名或复合类型的类型别名。例如,在下面的示例中, 1 typealias Point = (Int, Int) 2 let origin: Point = (0, 0) 在第二种情况下,类型标识符使用dot( var someValue: ExampleModule.MyType
类型标识符的语法 1 type-identifier → type-name generic-argument-clause opt | type-name generic-argument-clause opt . type-identifier 2 3 type-name → identifier 元组类型元组类型是以逗号分隔的类型列表,括在括号中。 您可以使用元组类型作为函数的返回类型,以使函数能够返回包含多个值的单个元组。您还可以命名元组类型的元素,并使用这些名称来引用各个元素的值。元素名称由标识符后跟冒号(:)组成。有关演示这两个功能的示例,请参阅具有多个返回值的函数。 当元组类型的元素具有名称时,该名称是该类型的一部分。 1 var someTuple = (top: 10, bottom: 12) // someTuple is of type (top: Int, bottom: Int) 2 someTuple = (top: 4, bottom: 42) // OK: names match 3 someTuple = (9, 99) // OK: names are inferred 4 someTuple = (left: 5, right: 5) // Error: names don't match 所有元组类型都包含两种或更多类型,除了 1 GRAMMAR OF A TUPLE TYPE 2 3 tuple-type → ( ) | ( tuple-type-element , tuple-type-element-list ) 4 5 tuple-type-element-list → tuple-type-element | tuple-type-element , tuple-type-element-list 6 7 tuple-type-element → element-name type-annotation | type 8 9 element-name → identifier 功能类型函数类型表示函数,方法或闭包的类型,由一个参数和由箭头( (parameter type) -> return type
的参数类型是类型逗号分隔的列表。因为返回类型可以是元组类型,所以函数类型支持返回多个值的函数和方法。 函数类型的参数(其中是任何类型)可以应用该属性在其调用站点隐式创建闭包。这提供了一种语法上方便的方法来推迟表达式的求值,而无需在调用函数时编写显式闭包。有关autoclosure函数类型参数的示例,请参见Autoclosures。 函数类型可以在其一个可变参数参数参数类型。从语法上讲,一个可变参数包含一个基本类型名称,后面紧跟三个点( 要指定输入输出参数,请在参数类型前加上 如果函数类型只有一个参数且该参数的类型是元组类型,则在编写函数类型时必须将元组类型括起来。例如,是一个函数的类型,它接受元组类型的单个参数,并且不返回任何值。相反,没有括号,是一个带有两个参数但不返回任何值的函数的类型。同样,因为是类型别名,函数类型与-a函数相同,该函数接受一个空元组的参数。这些类型与-a不带参数的函数不同。 函数和方法中的参数名称不是相应函数类型的一部分。例如: 1 func someFunction(left: Int, right: Int) {} 2 func anotherFunction(left: Int, right: Int) {} 3 func functionWithDifferentLabels(top: Int, bottom: Int) {} 4 5 var f = someFunction // The type of f is (Int, Int) -> Void, not (left: Int, right: Int) -> Void. 6 f = anotherFunction // OK 7 f = functionWithDifferentLabels // OK 8 9 func functionWithDifferentArgumentTypes(left: Int, right: String) {} 10 f = functionWithDifferentArgumentTypes // Error 11 12 func functionWithDifferentNumberOfArguments(left: Int, right: Int, top: Int) {} 13 f = functionWithDifferentNumberOfArguments // Error 因为参数标签不是函数类型的一部分,所以在编写函数类型时省略它们。 1 var operation: (lhs: Int, rhs: Int) -> Int // Error 2 var operation: (_ lhs: Int, _ rhs: Int) -> Int // OK 3 var operation: (Int, Int) -> Int // OK 如果函数类型包含多个箭头( 必须使用 Nonescaping闭包的限制作为非出错函数的参数不能存储在属性,变量或类型常量中 作为非出错函数的参数不能作为参数传递给另一个非出错函数参数。此限制有助于Swift在编译时而不是在运行时执行更多的检查以查看对内存的冲突访问。例如: 1 let external: (() -> Void) -> Void = { _ in () } 2 func takesTwoFunctions(first: (() -> Void) -> Void, second: (() -> Void) -> Void) { 3 first { first {} } // Error 4 second { second {} } // Error 5 6 first { second {} } // Error 7 second { first {} } // Error 8 9 first { external {} } // OK 10 external { first {} } // OK 11 } 在上面的代码中,两个参数 上例中标记为“Error”的四个函数调用会导致编译器错误。因为 如果需要避免此限制,请将其中一个参数标记为转义,或者使用该 1 GRAMMAR OF A FUNCTION TYPE 2 3 function-type → attributes opt function-type-argument-clause throwsopt -> type 4 5 function-type → attributes opt function-type-argument-clause rethrows -> type 6 7 function-type-argument-clause → ( ) 8 9 function-type-argument-clause → ( function-type-argument-list ...opt ) 10 11 function-type-argument-list → function-type-argument | function-type-argument , function-type-argument-list 12 13 function-type-argument → attributes opt inoutopt type | argument-label type-annotation 14 15 argument-label → identifier 数组类型Swift语言为Swift标准库 [type] 换句话说,以下两个声明是等效的: 1 let someArray: Array<String> = ["Alex", "Brian", "Dave"] 2 let someArray: [String] = ["Alex", "Brian", "Dave"] 在这两种情况下,常量 您可以通过嵌套方括号对来创建多维数组,其中元素的基本类型的名称包含在最里面的方括号对中。例如,您可以使用三组方括号创建三维整数数组: var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]] 在访问多维数组中的元素时,最左侧的下标索引引用最外层数组中该索引处的元素。右边的下一个下标索引是指数组中嵌套一个级别的索引处的元素。依此类推。这意味着在上面的示例中, 有关Swift标准库 1 GRAMMAR OF AN ARRAY TYPE 2 3 array-type → [ type ] 字典类型Swift语言为Swift标准库类型提供以下语法糖: [key type: value type] 换句话说,以下两个声明是等效的: 1 let someDictionary: [String: Int] = ["Alex": 31, "Paul": 39] 2 let someDictionary: Dictionary<String, Int> = ["Alex": 31, "Paul": 39] 在这两种情况下,常量都 可以通过在方括号中指定相应的键来通过下标来访问字典的值: 字典的键类型必须符合Swift标准库 有关Swift标准库 1 GRAMMAR OF A DICTIONARY TYPE 2 3 dictionary-type → [ type : type ] 可选类型Swift语言将后缀定义 1 var optionalInteger: Int? 2 var optionalInteger: Optional<Int> 在这两种情况下,变量 该类型 如果可选类型的实例包含值,则可以使用后缀运算符访问该值 1 optionalInteger = 42 2 optionalInteger! // 42 使用 您还可以使用可选链接和可选绑定来有条件地对可选表达式执行操作。如果值为 有关更多信息以及查看显示如何使用可选类型的示例,请参阅Optionals。 1 GRAMMAR OF AN OPTIONAL TYPE 2 3 optional-type → type ? 隐式展开的可选类型Swift语言将后缀定义 1 var implicitlyUnwrappedString: String! 2 var explicitlyUnwrappedString: Optional<String> 请注意,类型和类型之间不能出现空格 因为隐式解包会更改包含该类型的声明的含义,所以嵌套在元组类型或泛型类型中的可选类型(如字典或数组的元素类型)不能标记为隐式解包。例如: 1 let tupleOfImplicitlyUnwrappedElements: (Int!, Int!) // Error 2 let implicitlyUnwrappedTuple: (Int, Int)! // OK 3 4 let arrayOfImplicitlyUnwrappedElements: [Int!] // Error 5 let implicitlyUnwrappedArray: [Int]! // OK 由于隐式解包的选项 与optionals一样,如果在声明隐式展开的可选变量或属性时未提供初始值,则其值自动默认为 使用可选链接有条件地对隐式展开的可选表达式执行操作。如果值为 有关隐式展开的可选类型的更多信息,请参阅隐式展开的可选项。 1 GRAMMAR OF AN IMPLICITLY UNWRAPPED OPTIONAL TYPE 2 3 implicitly-unwrapped-optional-type → type ! 协议组成类型协议组合类型定义符合指定协议列表中的每个协议的类型,或者是给定类的子类并且符合指定协议列表中的每个协议的类型。只有在类型注释,通用参数子句和通用 协议组成类型具有以下形式: Protocol 1 & Protocol 2 协议组合类型允许您指定其类型符合多个协议要求的值,而无需显式定义从您希望类型符合的每个协议继承的新的命名协议。例如,可以使用的协议的组合物类型,而不是声明一个新的协议,从继承,,和。同样,您可以使用而不是声明作为子类并符合的新协议。 协议组合列表中的每个项目都是以下之一; 该列表最多可包含一个类:
当协议组合类型包含类型别名时,同一协议可能在定义中出现多次 - 重复项被忽略。例如, 1 typealias PQ = P & Q 2 typealias PQR = PQ & Q & R 1 GRAMMAR OF A PROTOCOL COMPOSITION TYPE 2 3 protocol-composition-type → type-identifier & protocol-composition-continuation 4 5 protocol-composition-continuation → type-identifier | protocol-composition-type 元类型元类型类型是指任何类型的类型,包括类类型,结构类型,枚举类型和协议类型。 类,结构或枚举类型的元类型是该类型的名称,后跟 您可以使用后缀 1 class SomeBaseClass { 2 class func printClassName() { 3 print("SomeBaseClass") 4 } 5 } 6 class SomeSubClass: SomeBaseClass { 7 override class func printClassName() { 8 print("SomeSubClass") 9 } 10 } 11 let someInstance: SomeBaseClass = SomeSubClass() 12 // The compile-time type of someInstance is SomeBaseClass, 13 // and the runtime type of someInstance is SomeSubClass 14 type(of: someInstance).printClassName() 15 // Prints "SomeSubClass" 有关更多信息,请参阅 使用初始化表达式从该类型的元类型值构造类型的实例。对于类实例,调用的初始值设定项必须使用 1 class AnotherSubClass: SomeBaseClass { 2 let string: String 3 required init(string: String) { 4 self.string = string 5 } 6 override class func printClassName() { 7 print("AnotherSubClass") 8 } 9 } 10 let metatype: AnotherSubClass.Type = AnotherSubClass.self 11 let anotherInstance = metatype.init(string: "some string") 1 GRAMMAR OF A METATYPE TYPE 2 3 metatype-type → type . Type | type . Protocol 类型继承子句类型继承子句用于指定命名类型从哪个类继承以及命名类型符合哪些协议。类型继承子句以冒号( 类类型可以从单个超类继承并符合任意数量的协议。定义类时,超类的名称必须首先出现在类型标识符列表中,然后是类必须符合的任意数量的协议。如果该类不从另一个类继承,则该列表可以以协议开头。有关类继承的扩展讨论和几个示例,请参阅继承。 其他命名类型只能继承或符合协议列表。协议类型可以从任何数量的其他协议继承。当协议类型继承自其他协议时,来自那些其他协议的要求集合在一起,并且从当前协议继承的任何类型必须符合所有这些要求。 枚举定义中的类型继承子句可以是协议列表,也可以是为其案例分配原始值的枚举,也可以是指定这些原始值类型的单个命名类型。有关使用类型继承子句指定其原始值类型的枚举定义的示例,请参阅原始值。 1 GRAMMAR OF A TYPE INHERITANCE CLAUSE 2 3 type-inheritance-clause → : type-inheritance-list 4 5 type-inheritance-list → type-identifier | type-identifier , type-inheritance-list 类型推断Swift广泛使用类型推断,允许您省略代码中许多变量和表达式的类型或部分类型。例如,您可以编写,完全省略类型,而不是写入,编译器正确地推断出名称类型的值。类似地,当可以从上下文推断出完整类型时,可以省略部分类型。 例如,如果您编写,编译器会推断出具有该类型的编译器。
在上面的两个例子中,类型信息从表达式树的叶子传递到它的根。也就是说,通过首先检查类型然后将此类型信息传递到根(变量)来推断 在Swift中,类型信息也可以以相反的方向流动 - 从根到叶。例如,在下面的示例中,常量上的显式类型注释()会导致数字文字具有推断类型而不是。 1 let e = 2.71828 // The type of e is inferred to be Double. 2 let eFloat: Float = 2.71828 // The type of eFloat is Float. Swift中的类型推断在单个表达式或语句的级别上运行。这意味着,必须可以通过对表达式或其子表达式之一进行类型检查来访问在表达式中推断省略类型或类型的一部分所需的所有信息。 |
请发表评论