在Swift中,函数实际上是一种特殊的组合体(闭包),你也可以定义匿名的组合体(闭包),将代码写在({})中,并使用in 来分隔参数和返回值.
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
EXPERIMENT // 练习题
Rewrite the closure to return zero for all odd numbers. // 重写编写一个组合体,返回值为0;
为了更精确的使用组合体(闭包),你可以有几种选择.当类型是明确的时候,比如代理的回调函数,你可以忽略它的参数的类型,以及返回值类型.单语句的组合体,隐式的返回它执行语句的值.
numbers.map({ number in 3 * number })
参数的指定使用数字取代名称,这个方法对于非常简短的组合体(闭包)特别适用. 一个组合体(闭包)作为函数的最后参数传递值的时候,可以紧跟在()后面.
sort([1, 5, 3, 12, 2]) { $0 > $1 }
Objects and Classes
/*对象和类*/
在Swift中,使用class关键字再加上类名来创建一个类.类中的成员/属性声明方法与之前的常量/变量声明一样,只是它们必须在类的定义内.同样,方法和函数也是如此.
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with (numberOfSides) sides."
}
}
EXPERIMENT // 练习题
Add a constant property with let, and add another method that takes an argument. //使用let添加一个常量属性,再添加一个带有参数的方法;
创建类的实例是在类名的后面加一个(),访问实例方法和实例成员使用点语法.
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
在上面的代码例子中,shape类缺少了一个非常重要的事情:当实例创建的时候,没有初始化.使用init可以创建一个初始化的实例.
class NamedShape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with (numberOfSides) sides."
}
}
注意上述代码中,self是怎样在初始化中区分name属性与name参数的.创建一个类的实例时,参数name的传递就像函数调用时一样.每个属性成员都需要分配一个值无论是在声明中还是在初始化里.
使用 deinit 定义一个注销对象的方法,在这个方法里你可以在对象被销毁前执行一些清理事情.
子类的写法是在类名后面使用:再加上父类的名称.在Swift中,不在要求子类必须有基础的根类,因此在恰当的时候,你可以根据情况需要添加或者去掉父类.
子类的方法可以覆盖(重写)父类中标记的 override的方法,如果覆盖(重写)了父类中没有标记override的方法,编译器会直接报错.编译器也会检测子类中标记为 override的方法,即使这个方法不是重载自父类.
class Square: NamedShape {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
override func simpleDescription() -> String {
return "A square with sides of length (sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
EXPERIMENT // 练习题
Make another subclass of NamedShape called Circle that takes a radius and a name as arguments to its initializer. Implement an area and a describe method on the Circle class.
/**设计一个继承NamedShape类的子类Circle,并初始化它的成员变量radius和name,再给类添加area和describe方法*/
类的另一种简便存取成员变量的方式是,使用setter和getter.
class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
override func simpleDescription() -> String {
return "An equilateral triagle with sides of length (sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength
在上述代码例子中,成员变量perimeter的setter方法有一个隐含的变量 newValue,也可以在set后添加(),在其中明显的定义这个变量.
注意在 EquilateralTriangle类中 初始化有三个不同的步骤:
- 设置子类声明的成员变量的值;
- 调用父类的初始化;
- 修改父类定义的成员变量值,以及其他的一些使用getter或者setter再或者实例方法来完成的工作.
/*************后续内容,敬请期待***********/