类的定义

类定义的关键字是 class,我们用 class + 类名 + “:” + 父类,比如定义一个 Person 类,类中去声明和定义变量和函数:

class Person: NSObject {
    var name: String
    public func sayHello(){
        print("Hello ~")
    } 
}

类的扩展

extension Person {  // 给人加一个飞的功能...
    func fly() {}
}

属性

存储属性

存储属性就是存储在类或者结构体一个实例里的一个常量和变量,用 var 或者 let 修饰。

但是如果一个结构体实例被声明为常量,那么即便这个结构体的某个属性是变量,也是不能去改变的:

let point = CGPoint(x: 1, y: 1)
point.x = 10    // 编译是不会通过的

延迟存储属性

lazy var nameLabel:UILabel = {
   let label = UILabel()
   // ...
   return label
}()

其实就是把一个立即执行的闭包的返回值赋值给属性,以达到懒加载的目的。

属性观察器

willSet 在新的值被设置之前调用 didSet 在新的值被设置之后立即调用 需要注意的是:当为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观察者。

计算属性

计算属性提供了一个 getter 和一个可选的 setter 。属性的 gettersetter 的关键词是 getset ,在 setter 中新值是 newValue

class Person: NSObject {
    var birthYear: Int
    var age : Int{
        set{
           self.age = newValue
           self.birthYear = 2016 - newValue
        }
    }
}

只读计算属性

当一个属性只有 getter 而没有 setter 时,那么它就是一个只读计算属性

类对象的实例和访问:

var person = Person()
person.age = 10

类的构造和析构

我们可以给 Person 自定义一个构造函数,构造函数中需要给所有的存储型属性一个赋值或者默认值:

init(name: String) {
   self.name = name
}

这样我们就可以用 name 来实例化一个对象: var person = Person(name:"Tom")

如果所有属性都有默认值,我们没有自定义的构造,系统会生成一个默认的构造函数:var person = Person() 相应的,如果我们自定义了一个构造函数,那么系统便不会为该类生成默认的构造函数。 但是,我们可以把自定义的构造函数写到类的扩展(extension)里,而不是类的原始定义里面。

与构造函数对应的是析构函数:deinit

指定构造器和便利构造器 指定构造器里面会初始化类实例所有的属性,所以为了保证继承的属性也能被初始化,子类的指定构造器都会调用父类的指定构造器,而类的便利构造器总是会调用本类的指定构造器。 也就是说:指定构造器需要向上调用,便利构造器需要横向调用

所以,我们可以把父类的指定构造函数重写成便利构造,却不能重写父类的便利构造。即便重写了父类的便利构造函数,但是由于我们不能直接调用父类的便利构造函数,所以不用给函数以 override 修饰。

必要构造器 如果某个构造函数被 required 修饰,那么该函数就是必要构造函数,子类继承该类时都必须要实现改构造函数。在子类重写父类的构造函数的时候,也要加 required 来修饰,以确定继承链上子类的子类也遵守。

除了构造和析构函数,类还有实例的私有函数、公共函数和静态函数。

类、函数的访问控制(访问、继承/重载 权限)

Swift 中的访问控制有 模块源文件 两个概念。用 “import” 导入的就是模块。

对于类而言的修饰词与权限:

修饰词 权限
open 修饰的类可以随意继承与访问
public 修饰的类只能在本模块内被继承,但是可以随便访问
internal 默认 - 模块内拥有访问权限
fileprivate 是文件外部不能被访问
private 是文件内部不能被访问
final 是文件内部也不能被继承

当然了,对于一个 internal 的类,其属性和方法的级别是不会超出类本身的,比如不可能是 public

函数也是同样的修饰词和权限,只是类的继承对应函数的重载权限。 函数除了以上几个,常用的修饰词还有 staticoverride

static修饰的是类方法。override修饰的是重写父类的方法。