11Methods
方法是与某个特定类相关联的函数。
类,结构体,和枚举都既可以定义成员方法,也可以定义类方法,类方法与oc中的概念相似。
相比之下,在oc中只有类可以定义方法。
11.1Instance Methods
成员方法就是那些属于某个实例,结构体,枚举的函数。
下面这个类定义三个成员方法
class Counter {
var count = 0
func increment() {
count++
}
func incrementBy(amount: Int) {
count += amount
}
func reset() {
count = 0
}
}
11.1.1Local and External Parameter Names for Methods
Function parameters can have both a local name (for use within the function’s body) and an external name (for use when calling the function)
函数的参数可以有局部名和外部名称
Swift gives the first parameter name in a method a local parameter name by default, and gives the second and subsequent parameter names both localand external parameter names by default.
默认情况下,方法的第一个参数只是局部名称,从第二个参数开始,它既是局部名称,也是外部名称
看看这个新版本的Counter类
class Counter {
var count: Int =0
func incrementBy(amount: Int, numberOfTimes: Int) {
count += amount * numberOfTimes
}
}
let counter =Counter()
counter.incrementBy(5, numberOfTimes:3)
// counter value is now 15
我们不需要给第一个参数增加外部名称,因为它的意义已用incrementby说明白了,从第二个参数开始才需要外部名称
还记得函数上把#号放在局部名称前,则局部名称也是外部名称吗。
swift的处理就好像从第二个参数开始,默认帮你加上#似的
11.1.2Modifying External Parameter Name Behavior for Methods
如果你确实想给第一个参数增加外部名称,那么你可以自己写一个上去,你可以用加#的方法。
相反,如果你不想从第二个开始有默认的外部名称呢,那么你可以在用“_”下划线作为显示外部名称。
11.1.3The self Property
每个实例都有一个隐式的属性self指向实例本身
在实际应用中,我们一般不需要写self,除非这个方法中得参数名与实例的属性名相同,这时需要用self来消除歧义
11.1.4Modifying Value Types from Within Instance Methods
结构体和枚举是值类型,默认的,不能在成员方法中修改值类型的属性
如果要修改则需要在方法前面加mutating关键字,这种修改甚至可以修改self属性,即修改整个实例
当然,如果这个实例是let常量,那么也不能调用mutating方法修改其属性值
struct Point {
var x = 0.0, y =0.0
mutating func moveByX(deltaX:Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
var somePoint =Point(x: 1.0, y:1.0)
somePoint.moveByX(2.0, y:3.0)
println("The point is now at (\(somePoint.x),\(somePoint.y))")
// prints "The point is now at (3.0, 4.0)"
let fixedPoint =Point(x: 3.0, y:3.0)
fixedPoint.moveByX(2.0, y:3.0)
// this will report an error
11.1.5Assigning to self Within a Mutating Method
mutating方法内修改结构体,枚举的self属性
struct Point {
var x = 0.0, y =0.0
mutating func moveByX(deltaX:Double, y deltaY: Double) {
self = Point(x:x + deltaX, y: y + deltaY)
}
}
enum TriStateSwitch {
case Off, Low, High
mutating func next() {
switch self {
case Off:
self = Low
case Low:
self = High
case High:
self = Off
}
}
}
var ovenLight =TriStateSwitch.Low
ovenLight.next()
// ovenLight is now equal to .High
ovenLight.next()
// ovenLight is now equal to .Off
11.2Type Methods
类方法
classes的类方法是在func前面加class关键字
structure和enumeration的类方法是在func前面加static关键字
类方法用类名和点来访问,不能通过实例和点来访问
类方法中得self指的是类,不是实例
类方法中可以调用和访问另一个类方法或属性,调用时可以省略self
12Subscripts
类,结构体,枚举都可以定义下标来访问集合,列表,序列的元素
12.1Subscript Syntax
其语法类似成员方法和计算属性的语法,使用subscript关键字
subscript(index:Int) -> Int {
get {
// return an appropriate subscript value here
}
set(newValue) { //newValue可以省略,默认的就是newValue
// perform a suitable setting action here
}
}
12.2Subscript Usage
var numberOfLegs = ["spider":8, "ant": 6, "cat": 4]
numberOfLegs["bird"] =2
这是Dictionary的一个例子,至于下标的实际意义由类来定。
12.3Subscript Options
下标可以有任意多个入参,入参可以是任意类型。下标可以返回任意类型。
可以使用变量参数和不定个数参数,但不能使用in-out参数,也不能有默认值
类和结构体可以有任意多个下标方法
定义多个下标方法,即下标重载
13Inheritance
类可以继承方法,属性和其他特性
继承下来的新类叫subclass,被继承的类叫superclass
类可以给继承下来的属性增加观察者,不管是存数属性还是计算属性都可以
13.1Defining a Base Class
Any class that does not inherit from another class is known as a base class.
一个不继承于其他类的类成为基类
NOTE
Swift classes do not inherit from a universal base class. Classes you define without specifying a superclass automatically become base classes for you to build upon.
swift类没有默认的父类,没有指定父类的类自动就是基类
下面定义一个基类
class Vehicle {
var currentSpeed = 0.0
var description: String {
return"traveling at \(currentSpeed) miles per hour"
}
func makeNoise() {
// do nothing - an arbitrary vehicle doesn't necessarily make a noise
}
}
let someVehicle =Vehicle()
println("Vehicle:\(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour
13.2Subclassing
class Bicycle:Vehicle {
var hasBasket = false
}
class Tandem:Bicycle {
var currentNumberOfPassengers = 0
}
13.3Overriding
子类可以覆盖实例方法,类方法,实例属性,类属性,下标方法。
写下“override”已明确表示你要覆盖父类的方法,以便编译器进行检查
13.3.1Accessing Superclass Methods, Properties, and Subscripts
覆盖后,如何访问父类的方法,属性,下标
super.someMethod() //方法
super.someProperty //属性
super[someIndex] //下标
13.3.2Overriding Methods
class Train:Vehicle {
override func makeNoise() {
println("Choo Choo")
}
}
let train =Train()
train.makeNoise()
// prints "Choo Choo"
13.3.3Overriding Properties
重写实例的属性和类属性,可在里面增加观察者
13.3.3.1Overriding Property Getters and Setters
可重写属性的get和set方法,不管是存储属性还是计算属性。
实际上,子类并不知道父类的这个属性到底是存储属性还是计算属性。
它只知道有这个类型的这个名称的属性。
You can present an inherited read-only property as a read-write property by providing both a getter and a setter in your subclass property override. You cannot, however, present an inherited read-write property as a read-only property.
如果父类的这个属性是只读属性,你可重写成可读可写属性,
但如果父类的这个属性是可读可写的,你不能重写成只读的。
class Car:Vehicle {
var gear = 1
override var description:String {
return super.description +" in gear \(gear)"
}
}
let car =Car()
car.currentSpeed =25.0
car.gear = 3
println("Car:\(car.description)")
// Car: traveling at 25.0 miles per hour in gear 3
13.3.3.2Overriding Property Observers
注意1
没法给常量存储属性和只读计算属性增加观察者,因为他们的值根本就不能改变,所以不应该有观察值(willSet, didSet)
注意2
同一个属性不应该既有setter又有willSet或didSet,因为willSet和didSet的内容可以在Setter里面实现。
class AutomaticCar:Car {
override var currentSpeed:Double {
didSet {
gear = Int(currentSpeed /10.0) + 1
}
}
}
let automatic =AutomaticCar()
automatic.currentSpeed =35.0
println("AutomaticCar:\(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4
我英语不好,这是值自动挡汽车么,当速度变化时,自动变档。。。
13.4Preventing Overrides
如果你的方法,属性,下标不想被重写,怎么办呢?在前面加final (final var, final func, final class func, final subscript)
如果类不想被继承,可以 final class