在iBooks上可以免费下载到这个的英文版本:The Swift Programming Language:
https://itunes.apple.com/us/book/swift-programming-language/id881256329?mt=11
本篇文章是我读里面的入门指南章节(The Swift Tour)所做的笔记,包括了摘抄、感想等等。
-----------------------------------------分割线-----------------------------------------
对象和类(Objects and Classes)
类的定义和使用,见下面摘抄自书上的例子。关键词是class,类构造器方法是init,自身就是self,父类就是super。里面的numberOfSides就是Property,用.来访问。
class Shape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
Property可以定义getter和setter,下面的newValue是关键字,表明是set进来的值。set之前和之后还可以分别调用两个方法willSet和didSet,但书上举的TriangleAndSquare的例子比较复杂,能不用最好。
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
var perimeter: Double {
//有willSet后不能定义get和set
willSet {
//do something before set
}
didSet {
//do something after set
}
}
其他细节:
1、deinit方法是类销毁时被调用的,通常做一些涉及资源的释放操作。
2、子类定义的方式,用冒号隔开:class Square: Shape {}
3、跟C#类似,覆盖父类方法的话,需要加关键词override,目的是使得开发者不会不知道而override:override func simpleDescription() -> String {}
4、方法里的参数可以定义个别名,用在方法实现里,比如后面的例子,times比较短,用在方法实现里可以比较简洁:func incrementBy(amount: Int, numberOfTimes times: Int)
书上提到的optional values,跟C#里面提到的可空类型基本一样,也是用问号(?)来定义。所以当一个对象是可空类型时,则对它的任何操作的返回值都是可空类型,,如果它的值为空,则返回值也是空。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
-----------------------------------------分割线-----------------------------------------
枚举和结构(Enumerations and Structures)
枚举用关键词enum,跟其他语言类似,第一个设置了值后,后续的会自动递增赋值。它里面还可以定义方法,挺特别的。toRaw()和fromRaw()两个方法分别用于转化成原始值以及从原始值(raw value)转化过来。枚举的类型可以不指定,默认应该就是Int,也可以指定类型,比如String或Float。
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.toRaw())
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()
if let convertedRank = Rank.fromRaw(3) {
let threeDescription = convertedRank.simpleDescription()
}
枚举居然还可以在初始化时为里面的成员赋值,而且可以不止一个,这个值跟原始值是不同的,原始值在定义该枚举后就确定了。下面的例子,那个success就绑定了两个String值。
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.")
结构用关键词struct。它跟类(class)很相近,最主要的区别就是,类是传引用(by reference),而结构是传值(先copy后)。
-----------------------------------------分割线-----------------------------------------
协议和扩展(Protocols and Extensions)
协议(Protocol)跟OC一样,也是只有方法定义却没有实现。类、枚举、结构都可以实现协议(adopt protocol),因为它们都可以定义方法。
相对OC,它支持的property比较好。下面还涉及到关键字mutating,它的意思是这个方法会改动到自身,主要是structure需要用。
Protocol跟JAVA的接口(Interface)是类似的,所以当我们把一个类型强制cast成某个Protocol后,它的除protocol外的方法、属性等就不可见了。
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
扩展(extension),对比OC,就是Category。这里特别的地方是,它可以直接用到已定义的protocol,见下面的例子,ExampleProtocol在上面已定义了:
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
7.simpleDescription
-----------------------------------------分割线-----------------------------------------
范型(Generics)
跟其他语言类似,定义范型用的是<>。用where这个关键字来限定范型类型需符合的条件,见下面一个比较复杂的例子:
func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.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])