继承 我们可以将共有的称为父类,自己所特有的称为子类,class 子类 : 父类,这就是继承.子类有父类的所有属性 在swift中,继承只能是单向的继承,也就是一个子类一般只有一个父类,而多继承可以通过遵从多个协议实现。也就说,一个类只能继承一个父类,但是可以遵循多个协议。
//父类: class Newclass1{ var math : Int = 99; var Chinese : Int = 87; var English : Int = 100; } //子类:拥有父类的所有属性 class Newclass2 : Newclass1 { } print (Newclass2.math); print (newclass2.Chinese); print (Newclass2.English); //父类: class person { var name : String; var age : Int; func description() -> String{ return "\(name) 年龄是 \(age)"; } init(){ name = ""; age = 3; } } //子类: class Student : person{ var school : String; override init(){ school = ""; super.init(); age = 18; } }构造函数调用规则 类的调用时,最先调用的是父类的构造函数,当所有的构造函数调用结束才进行方法的调用
class Person { var name : String; var age : Int; func description() -> String { print ("7777"); return "\(name) 年龄是 \(age)"; } convenience init(){ print ("1111"); self.init(name : "tony"); print ("6666"); self.age = 19; } convenience init(name : String) { print ("2222"); self.init(name : name, age : 18); } init (name : String, age : Int) { print ("5555"); self.name = name; self.age = age; } } class Student : Person { var school : String; init (name : String, age : Int, school : String){ print ("4444"); self.school = school; super.init (name : name, age : age); } convenience override init (name : String, age : Int) { print ("3333"); self.init (name : name, age : age, school : "sicnu"); } } let student = Student(); print (student.description());构造过程的安全检查 安全检查1 : 指定构造函数必须保证其所在类的所有存储属性都初始化完成,之后才能向上调用父类构造函数代理
class Animal { var name : String; init (){ self.name = "pig"; } } class Pig : Animal { var weight : Int; init (weight : Int, name : String){ self.weight = 200; super.init(); } } /* class Pig : Animal { var weight : Int; init (weight : Int, name : String){ super.init(); self.weight = 200; //错误,先初始化所有的子类属性 } } */安全检查2 : 指定构造函数必须先向上调用父类构造函数代理,然后再为继承的属性设置新值,否则指定构造函数赋予的新值将被父类中的构造函数所覆盖
class Student:Person{ var school:String; init (name:String, age:Int, school:String){ self.school = school; //self.name = "Tom" ; //错误,应该在调用父类之后修改,否则会被父类所覆盖 //self.age = 28; super.init(name:name, age:age); self.name = "Tom"; self.age = 28; } convenience override init (name:String, age:Int){ self.init(name:name, age:age, school:"sicnu"); } }安全检查3 : 便利构造函数必须先调用同一类中的其他构造函数代理,然后再为任意属性赋新值,否则便利构造函数赋予的新值将被同一类中的其他指定构造函数覆盖
class Student:Person{ var school:String; init (name:String, age:Int, school:String){ self.school = school; super.init(name:name, age:age); } convenience override init (name:String, age:Int){ //self.name = "Tom"; // 若先附初值,则会被父类的所覆盖 self.init(name:name, age:age, school:"sicnu") ; self.name = "Tom"; } }安全检查4构造函数在第一阶段构造完成之前不能调用实例方法,也不能读取实例属性,因为这时还不能保证要访问的实例属性已经被初始化
class Student:Person{ var school:String; init (name:String, age:Int, school:String){ self.school = school; //self.toString(); //不能再没有调用父类的super.init前调用实例属性; super.init(name:name, age:age); self.age = 11; self.toString(); } convenience override init (name:String, age:Int){ self.init(name:name, age:age, school:"sicnu"); self.name = "Tom"; self.age = 30; self.school = "sicnu"; //self.toString(); //这里可以调用 } func toString(){ print("Student : \(school) \(name) \(age)"); } }注意 : 两段式构造过程中,第一阶段构造完成的标志是:调用完父类指定构造函数,即super.init语句;如果没有调用父类的构造函数,则是调用完本身便利构造函数,即self.init语句
构造函数类继承
子类中没有定义任何指定构造函数,它将自动继承父类的所有指定构造函数
class Graduate:Student{ var special:String = ""; }重写实例属性 : 重写属性的getter和setter(计算静态属性需要这两个访问器,而计算存储属性不需要),你可以提供定制的 getter(或 setter)来重写任意继承来的属性,无论继承来的属性是存储型的还是计算型的属性。
class Person{ var name:String; var age:Int; func description() -> String{ return "\(name) 年龄是: \(age)"; } class func printClass() -> (){ print("Person 打印..."); } init(name:String, age:Int){ self.name = name; self.age = age; } } class Student:Person{ var school:String; override var age:Int{ get{ return super.age; } set{ super.age = newValue < 8 ? 8:newValue; } } convenience init(){ self.init(name:"Tony", age:18, school:"sicnu"); } init(name:String, age:Int, school:String){ self.school = school; super.init(name:name, age:age); } } let student1 = Student(); print("学生年龄: \(student1.age)"); student1.age = 6; print("学生年龄: \(student1.age)");从属性重写可见,子类本身并不存储数据,数据存储在父类的存储属性`
class Student:Person{ var school:String; override var age:Int{ willSet{ print("学生年龄新值: \(newValue)"); } didSet{ print("学生年龄旧值: \(oldValue)"); } } convenience init(){ self.init(name:"Tony", age:18, school:"sicnu"); } init(name:String, age:Int, school:String){ self.school = school; super.init(name:name, age:age); } }重写静态属性 静态方法使用class或static关键字,但是使用哪一个要看子类中是否重写该方法。class修饰的静态方法可以被重写,static关键字的就不能
class Account{ var amount:Double = 0.0 var owner:String = "" var interestRate:Double = 0.0668 //class不能换成static class var staticProp:Double{ return 0.0668 * 1_000_000 } var instanceProp:Double{ return self.interestRate * self.amount } } class TermAccount:Account{ //class换成static override class var staticProp:Double{ return 0.0700 * 1_000_000 } }