Welcome to Swift ,苹果官方Swift文档初译与注解六---35~44页

在Swift中,使用struct 创建结构体类型;结构体支持的行为与类非常相似,都有成员方法与初始化;结构体与类最大的区别是在代码中使用结构体的时候,它总是会被拷贝;但是类在使用的时候,只是采用引用方式.

   struct Card {

   var rank: Rank

   var suit: Suit

   func simpleDescription() -> String {

   return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"

   }

  }

  let threeOfSpades = Card(rank: .Three, suit: .Spades)

  let threeOfSpadesDescription = threeOfSpades.simpleDescription()

  EXPERIMENT // 练习题

  Add a method to Card that creates a full deck of cards, with one card of each combination of rank and suit. //给Card增加一个方法创建整副牌;并且带有一张包含rank 和suit的卡牌

一个枚举成员的实例可以拥有这个实例的关联值,多个枚举成员可以有不同的关联值;在创建成员实例的时候可以构建关联值.但是关联值与原始值是不同的:一个枚举成员的原始值,对于它的所有实例来说,都是相同的.并且,是你在定义枚举的时候构建的.

例如,有一种情况,从一个服务器上请求获取日出(sunrise)和日落(sunset)的时间,服务器要么响应信息,要么响应错误信息.

  enum ServerResponse {

   case Result(String, String)

   case Error(String)

  }

  let success = ServerResponse.Result("6:00 am", "8:09 pm")

  let failure = ServerResponse.Error("Out of cheese.")

  switch success {

  case let .Result(sunrise, sunset):

   let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."

  case let .Error(error):

   let serverResponse = "Failure... \(error)"

  }

  EXPERIMENT // 练习题

  Add a third case to ServerResponse and to the switch. // 添加第三个case给 ServerResponse 和 switch

Protocols and Extensions // 协议和扩展

使用protocol创建一个协议

  protocol ExampleProtocol {

   var simpleDescription: String { get }

   mutating func adjust()

  }

类,枚举,结构体都可以遵从协议;

  class SimpleClass: ExampleProtocol {

   var simpleDescription: String = "A very simple class."

   var anotherProperty: Int = 69105

   func adjust() {

   simpleDescription += " Now 100% adjusted."

   }

  }

  var a = SimpleClass()

  a.adjust()

  let aDescription = a.simpleDescription

  struct SimpleStructure: ExampleProtocol {

   var simpleDescription: String = "A simple structure"

   mutating func adjust() {

   simpleDescription += " (adjusted)"

   }

  }

  var b = SimpleStructure()

  b.adjust()

  let bDescription = b.simpleDescription”

  EXPERIMENT // 练习题

  Write an enumeration that conforms to this protocol. // 编写一个枚举,遵守协议;

注意在SimpleStructure结构体中使用的关键字 mutating(标记一个可以修改结构的方法), SimpleClass类的声明不需要任何标记 mutating的方法,因为类的方法总是可以修改类的.

使用extension给一个存在的类型添加功能,比如新的方法或者属性;也可以使用 extension 增加协议响应类型,甚至从库或者框架中导入的类型.

  extension Int: ExampleProtocol {

  var simpleDescription: String {

   return "The number \(self)"

   }

   mutating func adjust() {

   self += 42

   }

  }

  7.simpleDescription

  EXPERIMENT // 练习题

  Write an extension for the Double type that adds an absoluteValue property. // 给Double类型写一个扩展,增加一个 absoluteValue属性;

可以使用协议名(就像使用其他类型名一样 )来创建一个包含多种数据类型的对象集合来遵守单一协议.当你处理的一个协议类型的值时,协议的外部方法是无法访问的.

  let protocolValue: ExampleProtocol = a

  protocolValue.simpleDescription

在上面的代码中,变量protocolValue即使是动态运行时的SimpleClass类型,但编译器仍然将它当做指定的类型ExampleProtocol.这意味着你不可以附加了协议的类的方法和属性.

Generics // 泛型

在<>中填写一个名称可以来定义一个泛型函数或者类型;

  func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] {

   var result = ItemType[]()

   for i in 0..times {

   result += item

   }

   return result

  }

  repeat("knock", 4)

函数或者方法都可以使用泛型定义,(就像类,枚举和结构体它们一样)

   enum OptionalValue<T> {

   case None

   case Some(T)

  }

  var possibleInteger: OptionalValue<Int> = .None

  possibleInteger = .Some(100)

在类型名后面使用where关键字可以定义一个限制列表,例如,限制类型实现某一协议,或者要求两个类型相同,或者要求类继承某个父类.

  func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, .GeneratorType.Element == U.GeneratorType.Element>   (lhs: T, rhs: U) -> Bool {

   for lhsItem in lhs {

   for rhsItem in rhs {

   if lhsItem == rhsItem {

   return true

  }

   }

   }

   return false

  }

  anyCommonElements([1, 2, 3], [3])

  EXPERIMENT // 练习题

  Modify the anyCommonElements function to make a function that returns an array of the elements that any two sequences have in common.

// 修改 anyCommonElements函数,让它返回一个数组,数组的元素任何的两个序列都相同.(此句翻译可能有误)

在上面的例子中,你可以忽略 where ,在冒号后面只写协议名或者类名.写法 <T: Equatable>与写法<T where T: Equatable>作用是相同的.

(本章完)