diff --git a/source/chapter2/04_Collection_Types.md b/source/chapter2/04_Collection_Types.md index c8795de5..fda9f2b0 100755 --- a/source/chapter2/04_Collection_Types.md +++ b/source/chapter2/04_Collection_Types.md @@ -361,7 +361,7 @@ favoriteGenres.insert("Jazz") ```swift if let removedGenre = favoriteGenres.remove("Rock") { - print("\(removedValue)? I'm over it.") + print("\(removedGenre)? I'm over it.") } else { print("I never much cared for that.") } @@ -456,7 +456,7 @@ let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"] let cityAnimals: Set = ["🐦", "🐭"] houseAnimals.isSubsetOf(farmAnimals) // true -farmAnimals.isSuperSetOf(houseAnimals) +farmAnimals.isSupersetOf(houseAnimals) // true farmAnimals.isDisjointWith(cityAnimals) // true @@ -495,7 +495,7 @@ Swift 的字典使用`Dictionary`定义,其中`Key`是字典中键 我们可以像数组一样使用构造语法创建一个拥有确定类型的空字典: ```swift -var namesOfIntegers = [Int: String] +var namesOfIntegers = [Int: String]() // namesOfIntegers 是一个空的 [Int: String] 字典 ``` diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index 5023a0b6..d39d877c 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -283,7 +283,7 @@ Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的 每次调用`incrementor`时,其会以`amount`作为增量增加`runningTotal`的值。 ```swift -func makeIncrementor(forIncrement amount: Int) -> Void -> Int { +func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount @@ -293,7 +293,7 @@ func makeIncrementor(forIncrement amount: Int) -> Void -> Int { } ``` -`makeIncrementor`返回类型为`Void -> Int`。 +`makeIncrementor`返回类型为`() -> Int`。 这意味着其返回的是一个函数,而不是一个简单类型值。 该函数在每次调用时不接受参数只返回一个`Int`类型的值。 关于函数返回其他函数的内容,请查看[函数类型作为返回类型](../chapter2/06_Functions.html#function_types_as_return_types)。 @@ -315,16 +315,11 @@ func incrementor() -> Int { } ``` -`incrementor`函数并没有获取任何参数,但是在函数体内访问了`runningTotal`和`amount`变量。这是因为其通过捕获在包含它的函数体内已经存在的`runningTotal`和`amount`变量而实现。 - -由于没有修改`amount`变量,`incrementor`实际上捕获并存储了该变量的一个副本,而该副本随着`incrementor`一同被存储。 - -然而,因为每次调用该函数的时候都会修改`runningTotal`的值,`incrementor`捕获了当前`runningTotal`变量的引用,而不是仅仅复制该变量的初始值。捕获一个引用保证了当`makeIncrementor`结束时候并不会消失,也保证了当下一次执行`incrementor`函数时,`runningTotal`可以继续增加。 +`incrementer`函数并没有任何参数,但是在函数体内访问了`runningTotal`和`amount`变量。这是因为其通过捕获在包含它的函数体内已经存在的`runningTotal`和`amount`变量的引用(reference)而实现。捕捉了变量引用,保证了`runningTotal`和`amount`变量在调用完`makeIncrementer`后不会消失,并且保证了在下一次执行`incrementer`函数时,`runningTotal`可以继续增加。 > 注意: -> Swift 会决定捕获引用还是拷贝值。 -> 您不需要标注`amount`或者`runningTotal`来声明在嵌入的`incrementor`函数中的使用方式。 -> Swift 同时也处理`runingTotal`变量的内存管理操作,如果不再被`incrementor`函数使用,则会被清除。 +> 为了优化,Swift可能会捕捉和保存一份对值的拷贝,如果这个值是不可变或是在闭包外的。 +> Swift同样负责被捕捉的所有变量的内存管理,包括释放不被需要的变量。 下面代码为一个使用`makeIncrementor`的例子: diff --git a/source/chapter2/14_Initialization.md b/source/chapter2/14_Initialization.md index cf1149dc..9f2583fc 100755 --- a/source/chapter2/14_Initialization.md +++ b/source/chapter2/14_Initialization.md @@ -717,13 +717,13 @@ if anonymousCreature == nil { ``` > 注意: -空字符串(```""```)和一个值为```nil```的可选类型的字符串是两个完全不同的概念。上例中的空字符串(`""`)其实是一个有效的,非可选类型的字符串。这里我们只所以让`Animal`的可失败构造器,构建对象失败,只是因为对于`Animal`这个类的`species`属性来说,它更适合有一个具体的值,而不是空字符串。 +空字符串(`""`)和一个值为`nil`的可选类型的字符串是两个完全不同的概念。上例中的空字符串(`""`)其实是一个有效的,非可选类型的字符串。这里我们只所以让`Animal`的可失败构造器,构建对象失败,只是因为对于`Animal`这个类的`species`属性来说,它更适合有一个具体的值,而不是空字符串。 ###枚举类型的可失败构造器 你可以通过构造一个带一个或多个参数的可失败构造器来获取枚举类型中特定的枚举成员。还能在参数不满足你所期望的条件时,导致构造失败。 -下例中,定义了一个名为TemperatureUnit的枚举类型。其中包含了三个可能的枚举成员(```Kelvin```,```Celsius```,和 ```Fahrenheit```)和一个被用来找到```Character```值所对应的枚举成员的可失败构造器: +下例中,定义了一个名为TemperatureUnit的枚举类型。其中包含了三个可能的枚举成员(`Kelvin`,`Celsius`,和 `Fahrenheit`)和一个被用来找到`Character`值所对应的枚举成员的可失败构造器: ```swift enum TemperatureUnit { @@ -761,7 +761,7 @@ if unknownUnit == nil { ###带原始值的枚举类型的可失败构造器 -带原始值的枚举类型会自带一个可失败构造器```init?(rawValue:)```,该可失败构造器有一个名为```rawValue```的默认参数,其类型和枚举类型的原始值类型一致,如果该参数的值能够和枚举类型成员所带的原始值匹配,则该构造器构造一个带此原始值的枚举成员,否则构造失败。 +带原始值的枚举类型会自带一个可失败构造器`init?(rawValue:)`,该可失败构造器有一个名为`rawValue`的默认参数,其类型和枚举类型的原始值类型一致,如果该参数的值能够和枚举类型成员所带的原始值匹配,则该构造器构造一个带此原始值的枚举成员,否则构造失败。 因此上面的 TemperatureUnit的例子可以重写为: @@ -785,9 +785,9 @@ if unknownUnit == nil { ###类的可失败构造器 -值类型(如结构体或枚举类型)的可失败构造器,对何时何地触发构造失败这个行为没有任何的限制。比如在前面的例子中,结构体```Animal```的可失败构造器触发失败的行为,甚至发生在`species`属性的值被初始化以前。而对类而言,就没有那么幸运了。类的可失败构造器只能在所有的类属性被初始化后和所有类之间的构造器之间的代理调用发生完后触发失败行为。 +值类型(如结构体或枚举类型)的可失败构造器,对何时何地触发构造失败这个行为没有任何的限制。比如在前面的例子中,结构体`Animal`的可失败构造器触发失败的行为,甚至发生在`species`属性的值被初始化以前。而对类而言,就没有那么幸运了。类的可失败构造器只能在所有的类属性被初始化后和所有类之间的构造器之间的代理调用发生完后触发失败行为。 -下例子中,定义了一个名为```Product```的类,其内部结构和结构体```Animal```很相似,内部也有一个名为```name```的```String```类型的属性。由于该属性的值同样不能为空字符串,所以我们加入了可失败构造器来确保该类满足上述条件。但由于```Product```类不是一个结构体,所以当想要在该类中添加可失败构造器触发失败条件时,必须确保```name```属性被初始化。因此我们把```name```属性的```String```类型做了一点点小小的修改,把其改为隐式解析可选类型(```String!```),来确保可失败构造器触发失败条件时,所有类属性都被初始化了。因为所有可选类型都有一个默认的初始值```nil```。因此最后```Product```类可写为: +下例子中,定义了一个名为`Product`的类,其内部结构和结构体`Animal`很相似,内部也有一个名为`name`的`String`类型的属性。由于该属性的值同样不能为空字符串,所以我们加入了可失败构造器来确保该类满足上述条件。但由于`Product`类不是一个结构体,所以当想要在该类中添加可失败构造器触发失败条件时,必须确保`name`属性被初始化。因此我们把`name`属性的`String`类型做了一点点小小的修改,把其改为隐式解析可选类型(`String!`),来确保可失败构造器触发失败条件时,所有类属性都被初始化了。因为所有可选类型都有一个默认的初始值`nil`。因此最后`Product`类可写为: ```swift class Product { @@ -799,7 +799,7 @@ class Product { } ``` -因为```name```属性是一个常量,所以一旦```Product```类构造成功,```name```属性肯定有一个非```nil```的值。因此完全可以放心大胆的直接访问```Product```类的```name```属性,而不用考虑去检查```name```属性是否有值。 +因为`name`属性是一个常量,所以一旦`Product`类构造成功,`name`属性肯定有一个非`nil`的值。因此完全可以放心大胆的直接访问`Product`类的`name`属性,而不用考虑去检查`name`属性是否有值。 ```swift if let bowTie = Product(name: "bow tie") { @@ -818,7 +818,7 @@ if let bowTie = Product(name: "bow tie") { >注意: 可失败构造器也可以代理调用其它的非可失败构造器。通过这个方法,你可以为已有的构造过程加入构造失败的条件。 -下面这个例子,定义了一个名为```CartItem```的```Product```类的子类。这个类建立了一个在线购物车中的物品的模型,它有一个名为```quantity```的常量参数,用来表示该物品的数量至少为1: +下面这个例子,定义了一个名为`CartItem`的`Product`类的子类。这个类建立了一个在线购物车中的物品的模型,它有一个名为`quantity`的常量参数,用来表示该物品的数量至少为1: ```swift class CartItem: Product { @@ -831,13 +831,13 @@ class CartItem: Product { } ``` -和```Product```类中的```name```属性相类似的,```CartItem```类中的```quantity```属性的类型也是一个隐式解析可选类型,只不过由(```String!```)变为了(```Int!```)。这样做都是为了确保在构造过程中,该属性在被赋予特定的值之前能有一个默认的初始值nil。 +和`Product`类中的`name`属性相类似的,`CartItem`类中的`quantity`属性的类型也是一个隐式解析可选类型,只不过由(`String!`)变为了(`Int!`)。这样做都是为了确保在构造过程中,该属性在被赋予特定的值之前能有一个默认的初始值nil。 -可失败构造器总是先向上代理调用基类,```Product```的构造器 ```init(name:)```。这满足了可失败构造器在触发构造失败这个行为前必须总是执行构造代理调用这个条件。 +可失败构造器总是先向上代理调用基类,`Product`的构造器 `init(name:)`。这满足了可失败构造器在触发构造失败这个行为前必须总是执行构造代理调用这个条件。 -如果由于```name```的值为空而导致基类的构造器在构造过程中失败。则整个`CartIem`类的构造过程都将失败,后面的子类的构造过程都将不会被执行。如果基类构建成功,则继续运行子类的构造器代码。 +如果由于`name`的值为空而导致基类的构造器在构造过程中失败。则整个`CartIem`类的构造过程都将失败,后面的子类的构造过程都将不会被执行。如果基类构建成功,则继续运行子类的构造器代码。 -如果你构造了一个```CartItem```对象,并且该对象的```name```属性不为空以及```quantity```属性为1或者更多,则构造成功: +如果你构造了一个`CartItem`对象,并且该对象的`name`属性不为空以及`quantity`属性为1或者更多,则构造成功: ```swift if let twoSocks = CartItem(name: "sock", quantity: 2) { @@ -845,7 +845,7 @@ if let twoSocks = CartItem(name: "sock", quantity: 2) { } // 打印 "Item: sock, quantity: 2" ``` -如果你构造一个```CartItem```对象,其```quantity```的值```0```, 则```CartItem```的可失败构造器触发构造失败的行为: +如果你构造一个`CartItem`对象,其`quantity`的值`0`, 则`CartItem`的可失败构造器触发构造失败的行为: ```swift if let zeroShirts = CartItem(name: "shirt", quantity: 0) { @@ -856,7 +856,7 @@ if let zeroShirts = CartItem(name: "shirt", quantity: 0) { // 打印 "Unable to initialize zero shirts" ``` -类似的, 如果你构造一个```CartItem```对象,但其```name```的值为空, 则基类```Product```的可失败构造器将触发构造失败的行为,整个```CartItem```的构造行为同样为失败: +类似的, 如果你构造一个`CartItem`对象,但其`name`的值为空, 则基类`Product`的可失败构造器将触发构造失败的行为,整个`CartItem`的构造行为同样为失败: ```swift if let oneUnnamed = CartItem(name: "", quantity: 1) { @@ -876,7 +876,7 @@ if let oneUnnamed = CartItem(name: "", quantity: 1) { >注意: 你可以用一个非可失败构造器重写一个可失败构造器,但反过来却行不通。 -下例定义了一个名为```Document```的类,这个类中的```name```属性允许为```nil```和一个非空字符串,但不能是一个空字符串: +下例定义了一个名为`Document`的类,这个类中的`name`属性允许为`nil`和一个非空字符串,但不能是一个空字符串: ```swift class Document { @@ -891,7 +891,7 @@ class Document { } ``` -下面这个例子,定义了一个名为```AutomaticallyNamedDocument```的```Document```类的子类。这个子类重写了基类的两个指定构造器。确保了不论在何种情况下```name```属性总是有一个非空字符串```[Untitled]```的值。 +下面这个例子,定义了一个名为`AutomaticallyNamedDocument`的`Document`类的子类。这个子类重写了基类的两个指定构造器。确保了不论在何种情况下`name`属性总是有一个非空字符串`[Untitled]`的值。 ```swift class AutomaticallyNamedDocument: Document { @@ -910,20 +910,20 @@ class AutomaticallyNamedDocument: Document { } ``` -```AutomaticallyNamedDocument```用一个非可失败构造器```init(name:)```,重写了基类的可失败构造器```init?(name:)```。因为子类用不同的方法处理了```name```属性的值为一个空字符串的这种情况。所以子类将不再需要一个可失败的构造器。 +`AutomaticallyNamedDocument`用一个非可失败构造器`init(name:)`,重写了基类的可失败构造器`init?(name:)`。因为子类用不同的方法处理了`name`属性的值为一个空字符串的这种情况。所以子类将不再需要一个可失败的构造器。 ###可失败构造器 init! -通常来说我们通过在```init```关键字后添加问号的方式来定义一个可失败构造器,但你也可以使用通过在```init```后面添加惊叹号的方式来定义一个可失败构造器```(init!)```,该可失败构造器将会构建一个特定类型的隐式解析可选类型的对象。 +通常来说我们通过在`init`关键字后添加问号的方式来定义一个可失败构造器,但你也可以使用通过在`init`后面添加惊叹号的方式来定义一个可失败构造器`(init!)`,该可失败构造器将会构建一个特定类型的隐式解析可选类型的对象。 -你可以在 ```init?```构造器中代理调用 ```init!```构造器,反之亦然。 -你也可以用 ```init?```重写 ```init!```,反之亦然。 -你还可以用 ```init```代理调用```init!```,但这会触发一个断言:是否 ```init!```构造器会触发构造失败? +你可以在 `init? `构造器中代理调用 `init!`构造器,反之亦然。 +你也可以用 `init?`重写 `init!`,反之亦然。 +你还可以用 `init`代理调用`init!`,但这会触发一个断言:是否 `init!` 构造器会触发构造失败? ##必要构造器 -在类的构造器前添加```required```修饰符表明所有该类的子类都必须实现该构造器: +在类的构造器前添加 `required` 修饰符表明所有该类的子类都必须实现该构造器: ```swift class SomeClass { @@ -932,7 +932,7 @@ class SomeClass { } } ``` -当子类重写基类的必要构造器时,必须在子类的构造器前同样添加```required```修饰符以确保当其它类继承该子类时,该构造器同为必要构造器。在重写基类的必要构造器时,不需要添加```override```修饰符: +当子类重写基类的必要构造器时,必须在子类的构造器前同样添加`required`修饰符以确保当其它类继承该子类时,该构造器同为必要构造器。在重写基类的必要构造器时,不需要添加`override`修饰符: ```swift class SomeSubclass: SomeClass { diff --git a/source/chapter3/05_Declarations.md b/source/chapter3/05_Declarations.md index be67b2ec..cc141e17 100755 --- a/source/chapter3/05_Declarations.md +++ b/source/chapter3/05_Declarations.md @@ -495,6 +495,20 @@ plusOne(10) 这种形式中,每一个事件块由关键字`case`开始,后面紧接着一个或多个以逗号分隔的枚举事件。每一个事件名必须是独一无二的。每一个事件也可以指定它所存储的指定类型的值,这些类型在*关联值类型(associated values types)*的元组里被指定,立即书写在事件 名后。获得更多关于关联值类型的信息和例子,请查看[关联值(Associated Values)](TODO)一节。 +枚举有一个递归结构,就是说,枚举有着枚举类型自身实例的关联值的事件。然而,枚举类型的实例有值语义,意味着它们在内存中有着固定的位置。为了支持递归,编译器必需插入一个间接层。 + +为间接使用特殊的枚举事件,使用`indirect`声明修饰符标记。 + +> enum Tree { +> case Empty +> indirect case Node(value: T, left: Tree, right:Tree) +> } + +为了间接的使用一个枚举的所有事件,使用`indirect`修饰符标记整个枚举-当枚举有许多事件且每个事件都需要使用`indirect`修饰符标记的时候这将非常便利。 + +一个被`indirect`修饰符标记的枚举事件必需有一个关联值。一个使用`indirect`修饰符标记的枚举包含有着关联值的事件和没有关联值的事件的混合。就是说,它不能包含任何也使用`indirect`修饰符标记的事件。 + + ###使用原始值类型事件的枚举(Enumerations with Cases of a Raw-Value Type) @@ -505,9 +519,9 @@ plusOne(10) > case `enumeration case 2` = `raw value 2` > } -在这种形式中,每一个事件块由`case`关键字开始,后面紧接着一个或多个以逗号分隔的枚举事件。和第一种形式的枚举事件不同,这种形式的枚举事件包含一个同类型的基础值,叫做*原始值(raw value)*。这些值的类型在*原始值类型(raw-value type)*中被指定,必须表示一个整数,浮点数,字符串,或者一个字符。特别是*原始值类型(raw-value type)*必需遵守`Equatable`类型的协议和下列形式中的一种字面量构造协议(literal-convertible protocols):整型字面量有`IntergerLiteralConvertible`,浮点行字面量有`FloatingPointLiteralConvertible`,包含任意数量字符的字符串型字面量有`StringLiteralConvertible`,仅包含一个单一字符的字符串型字面量有`ExtendedGraphemeClusterLiteralConvertible`。 - -每一个事件必须有唯一的名字,必须有一个唯一的初始值。如果初始值类型被指定为`Int`,则不必为事件显式的指定值,它们会隐式的被标为值`0,1,2`等。每一个没有被赋值的`Int`类型时间会隐式的赋予一个初始值,它们是自动递增的。 +在这种形式中,每一个事件块由`case`关键字开始,后面紧接着一个或多个以逗号分隔的枚举事件。和第一种形式的枚举事件不同,这种形式的枚举事件包含一个同类型的基础值,叫做*原始值(raw value)*。这些值的类型在*原始值类型(raw-value type)*中被指定,必须表示一个整数,浮点数,字符串,或者一个字符。特别是*原始值类型(raw-value type)*必需遵守`Equatable`类型的协议和下列形式中的一种字面量构造协议(literal-convertible protocols):整型字面量有`IntergerLiteralConvertible`,浮点行字面量有`FloatingPointLiteralConvertible`,包含任意数量字符的字符串型字面量有`StringLiteralConvertible`,仅包含一个单一字符的字符串型字面量有`ExtendedGraphemeClusterLiteralConvertible`。每一个事件必须有唯一的名字,必须有一个唯一的初始值。 + +如果初始值类型被指定为`Int`,则不必为事件显式的指定值,它们会隐式的被标为值`0,1,2`等。每一个没有被赋值的`Int`类型时间会隐式的赋予一个初始值,它们是自动递增的。 ```Swift num ExampleEnum: Int { @@ -517,6 +531,14 @@ num ExampleEnum: Int { 在上面的例子中,`ExampleEnum.A`的值是`0`,`ExampleEnum.B`的值是`1`。因为`ExampleEnum.C`的值被显式的设定为`5`,因此`ExampleEnum.D`的值会自动增长为`6`。 +如果原始值类型被指定为`String`类型,你不用明确的为事件指定值,每一个没有指定的事件会隐式地用与事件名字相同的字符串指定。 + +> enum WeekendDay: String { +> case Saturday, Sunday +> } + +在上面这个例子中,`WeekendDay.Saturday`的原始值是`"Saturday"`,`WeekendDay.Sunday`的原始值是`"Sunday"`。 + 拥有多种事件的原始值类型的枚举含蓄地遵循定义在Swift标准库中的`RawRepresentable`协议。所以,它们拥有一个原始值(`rawValue`)属性和一个有着`init?(rawValue: RawValue)`签名的可失败构造器(a failable initializer)。可以使用原始值属性去取的枚举事件的原始值,就像在`ExampleEnum.B.rawValue`中一样。如果有一个事件符合,也可以使用原始值去找到一个符合的事件,通过调用枚举的可失败构造器,如`ExampleEnum(rawValue: 5)`,这个可失败构造器返回一个可选的事件。想得到更多的信息和关于原始值类型查看更多信息和获取初始值类型事件的信息,参阅初始值[原始值(Raw Values)](TODO)。 @@ -530,10 +552,10 @@ num ExampleEnum: Int { > 枚举声明语法 > *枚举声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修饰符*](TODO) _可选_ [*联合式枚举*](TODO) > *枚举声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修饰符*](TODO) _可选_ [*原始值式枚举*](..\chapter3\05_Declarations.html#raw_value_style_enum) -> *联合式枚举* → **enum** [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [类型继承子句](TODO)_可选_ **{** [*union-style-enum-members*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_ **}** +> *联合式枚举* → **indirect** _可选_ **enum** [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [类型继承子句](TODO)_可选_ **{** [*union-style-enum-members*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_ **}** > *union-style-enum-members* → [*union-style-enum-member*](..\chapter3\05_Declarations.html#union_style_enum_member) [*union-style-enum-members*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_ > *union-style-enum-member* → [*声明*](..\chapter3\05_Declarations.html#declaration) | [*联合式(Union Style)的枚举case子句*](..\chapter3\05_Declarations.html#union_style_enum_case_clause) -> *联合式(Union Style)的枚举case子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **case** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list) +> *联合式(Union Style)的枚举case子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **indirect** _可选_ **case** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list) > *联合式(Union Style)的枚举case列表* → [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) | [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) **,** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list) > *联合式(Union Style)的case* → [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组类型*](..\chapter3\03_Types.html#tuple_type) _可选_ > *枚举名* → [*标识符*](LexicalStructure.html#identifier) diff --git a/source/chapter3/06_Attributes.md b/source/chapter3/06_Attributes.md index e6063258..603f8cf2 100755 --- a/source/chapter3/06_Attributes.md +++ b/source/chapter3/06_Attributes.md @@ -95,7 +95,7 @@ class MyClass { 该特性用于修饰任何可以在Objective-C中表示的声明。比如,非嵌套类、协议、非泛型枚举(仅限整型值类型)、类和协议的属性和方法(包括`getter`和`setter`)、构造器、析构器以及下标。`objc`特性告诉编译器这个声明可以在Objective-C代码中使用。 -如果你将`objc`特性应用于一个类或协议,它也会隐式地应用于那个类的成员或协议。对于标记了`objc`特性的类,编译器会隐式地为它的子类添加`objc`特性。标记了`objc`特性的协议不能继承没有标记`objc`的协议。 +标有`objc`特性的类必须继承自Objective-C中定义的类。如果你将`objc`特性应用于一个类或协议,它也会隐式地应用于那个类的成员或协议。对于标记了`objc`特性的类,编译器会隐式地为它的子类添加`objc`特性。标记了`objc`特性的协议不能继承没有标记`objc`的协议。 如果你将`objc`特性应用于枚举,每一个枚举的`case`都会以枚举名称和`case`名称组合的方式暴露在Objective-C代码中。例如:一个名为`Venus`的`case`在`Planet`枚举中,这个`case`暴露在Objective-C代码中时叫做`PlanetVenus`。