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>作用是相同的.
(本章完)