类继承2
来源:互联网 发布:手机乐云记事 数据丢失 编辑:程序博客网 时间:2024/05/18 09:52
重写实例方法
在子类中,你可以重写继承来的实例方法或类方法,提供一个定制或替代的方法实现。
class Person{ var name:String var age:Int func description() -> String{ //定义实例方法description 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 convenience init(){ self.init(name:"Tony", age:18, school:"四川师范大学") } init(name:String, age:Int, school:String){ self.school = school super.init(name:name, age:age) } override func description() -> String { //在子类中重写方法 print("父类打印 \(super.description())") //调用父类方法,super代指父类 return "\(name) 年龄是: \(age), 所在学校: \(school)。" } override class func printClass() ->(){ //重写静态方法 print("Student 打印...") }}let student1 = Student()print("学生1: \(student1.description())")Person.printClass()Student.printClass()//输出结果://父类打印 Tony 年龄是:18//学生1:Tony 年龄是:18,所在学校:清华大学。//Person 打印...//Student 打印...
重写静态方法
静态方法使用class或static关键字,但是使用哪一个要看子类中是否重写该方法。class修饰的静态方法可以被重写,static关键字的就不能。
class Account{ var owner:String = "Tony" //账户名 //class不能换成static class func interestBy(amount:Double) -> Double{ //定义静态方法 return 0.08886 * amount }}class TermAccount:Account{ //定期账户 //class可以换成static override class func interestBy(amount:Double) -> Double{ //重写静态方法 这里的class可以换成static 除非在TermAccount的子类重写interestBy return 0.09 * amount }}//调用静态方法print(Account.interestBy(10_000.00))print(TermAccount.interestBy(10_000.00))
下标重写
对下标的重写同子类属性重写一样也是重写下标的getter和setter访问器
class DoubleDimensionalArray{ let rows:Int, columns:Int var grid:[Int] init(rows:Int, columns:Int){ self.rows = rows self.columns = columns grid = Array(repeating:0, count:rows * columns) } subscript(row:Int , col:Int)->Int{ //定义下标 get{ return grid[(row * columns) + col] } set{ grid[(row * columns) + col] = newValue } }}class SquareMatrix:DoubleDimensionalArray{ //类的继承 override subscript(row:Int, col:Int)->Int{ //重写父类下标 get{ return super.grid[(row * columns) + col] } set{ super.grid[(row * columns) + col] = newValue * newValue//给父类grid属性附值 } }}var ary2 = SquareMatrix(rows: 5, columns: 5)for var i in 0..<5{ for var j in 0..<5{ ary2[i, j] = i + j }}for var i in 0..<5{ for var j in 0..<5{ print("\t \(ary2[i, j])", terminator:" ") } print("\n")}
使用final关键字
我们可以在类的定义中使用final关键字声明类、属性、方法和下标。final声明的类不能被继承,final声明的属性、方法、和下标不能被重写。
final class Person{ //声明final ,说明Person类不能被继承 var name:String final var age:Int final func description() -> String{ return "\(name) 年龄是: \(age)" } final class func printClass() -> (){ print("Person 打印...") } init(name:String, age:Int){ self.name = name self.age = age }}class Student:Person{ //报错 var school:String convenience init(){ self.init(name: "Tony", age:18, school:"清华大学") } init(name:String, age:Int, school:String){ self.school = school super.init(name:name, age:age) } override func description() -> String { //报错 print("父类打印 \(super.description())") return "\(name) 年龄是: \(age), 所在学校: \(school)。" } override class func printClass() -> (){ //报错 print("Student 打印...") } override var age:Int{ //报错 get{ return super.age } set{ super.age = newValue < 8 ? 8: newValue } }}
类型检查与转换
定义一个类的继承
class Person{ var name:String var age:Int func description() -> String{ return "\(name) 年龄是: \(age)" } convenience init(){//便利构造函数 self.init(name: "Tony")//调用本类的第二个(其他)便利构造函数 self.age = 19 } convenience init(name:String){//便利构造函数 self.init(name: name, age:8)//调用同一类(下面)的指定构造函数 } init(name:String, age:Int){//指定构造函数 self.name = name self.age = age }}class Student:Person{ var school:String init (name:String, age:Int, school:String){//指定构造函数 self.school = school super.init(name:name, age:age)//调用Person中的指定构造函数 }}class Worker:Person{ var factory:String init(name:String, age:Int, factory:String){ self.factory = factory super.init(name:name, age:age) }}
使用is进行类型检查,它可以判断一个实例是否是某个类的类型。如果实例是目标类型,结果返回true,否则返回false
let student1 = Student(name:"Tom", age:18, school:"清华大学")let student2 = Student(name: "Ben", age: 28, school: "北京大学")let student3 = Student(name: "Tony", age: 38, school: "香港大学")let worker1 = Worker(name: "Tom", age: 18, factory: "钢厂")let worker2 = Worker(name: "Ben", age: 20, factory: "电厂")let people = [student1, student2, student3, worker1, worker2]//把实例放进数组集合中var studentCount = 0var workerCount = 0for item in people{ //用循环判断其属于哪个子类 if item is Worker{ workerCount = workerCount + 1 }else if item is Student{ studentCount = studentCount + 1 }}print("工人人数: \(workerCount), 学生人数: \(studentCount)。")
使用as、as!和as?进行类型转换
某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用类型转换操作符(as? 或 as!)。
因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式(conditional form)as? 返回一个你试图向下转成的类型的可选值(optional value)。强制形式 as! 把试图向下转型和强制解包(force-unwraps)转换结果结合为一个操作。
//当你不确定向下转型可以成功时,用类型转换的条件形式(as?)。条件形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 nil。这使你能够检查向下转型是否成功。只有你可以确定向下转型一定会成功时,才使用强制形式(as!)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。
let p1:Person = Student(name: "Tom", age: 20, school: "清华大学")let p2:Person = Worker(name: "Tom", age: 18, factory: "钢厂")let p3:Person = Person(name: "Tom", age: 28)let p4:Student = Student(name: "Ben", age: 40, school: "北京大学")let p5:Worker = Worker(name: "Tony", age: 28, factory: "电厂")
创建了实例,p1、p4是Student实例,p2、p5是Work实例,p3是Person实例
类型转换有两个方向:向下转型——将父类类型转换为子类类型,向上转型——将子类类型转换为父类类型。通常情况下的类型转换都是向下转型
as操作符在类中仅仅只用于向上转型,很少用.还可以进行模式匹配
let p41:Person = p4 as Person//向上转型let p41:Person = p4
将Student类型的p4转化为Person类型是向上转型,向上转型通常可以省略as Person部分。
as!操作符可以应用于三种情况:将非可选类型为非可选类型/将可选类型为非可选类型/将可选类型为可选类型
//1.将非可选类型为非可选类型let p11 = p1 as! Student//let p111 = p2 as! Student //报错 在转换过程中不能转换为目标类型//2.将可选类型为非可选类型let p6 :Person? = Student(name: "Tom", age: 20, school: "清华大学")let p12 = p6 as! Student//报错 p6为nil as!在转换过程对可选址进行拆包 //3.将可选类型为可选类型let p13 = p6 as! Student?//可选类型转换为可选类型
as?操作符可以应用于两种情况:将非可选类型为可选类型, 将可选为可选
//向上转型,使用as?//将非可选类型为可选类型let p21 = p1 as? Studentlet p211 = p2 as? Studentprint(p21)print(p211)//将可选为可选let p7 :Person? = Student(name: "Tom", age: 20, school: "清华大学")let p22 = p7 as? Student?print(p7)print(p22)var arr = [p1, p2, p3, p4, p5]var i:Int = 1for item in arr{ if let m = item as? Worker{ print("Worker factory: \(m.factory)") }else if let n = item as? Student{ print("Student school: \(n.school)") } i += 1}let stud1 = arr[0] as? Student //它是Student可选类型,具体使用时往往还需要拆包print(stud1)print(stud1!.school)let woker1 = arr[1] as! Workerprint(woker1)print(woker1.name)
所以我们在使用as?操作符进行类型转换时你最好采用可选绑定方式,也就是将转换语句放到if或while语句中
两种不确定的类型:Any类型和AnyObject类型
AnyObject:任何类的类型, Any:任何类型
let people1:[Person] = [student1, student2, student3, worker1, worker2]let people2:[AnyObject] = [student1, student2, student3, worker1, worker2]let people3:[Any] = [student1,student2,student3, worker1, worker2]for item in people2{ if let Student = item as? Student{ print("Student school: \(Student.school)") }else if let Worker = item as? Worker{ print("Worker factory: \(Worker.factory)") }}let w1:AnyObject = arr[1] as! Worker
使用Any类型来和混合的不同类型一起工作,包括函数类型和非类类型
var things = [Any]()//创建了一个可以存储Any类型的数组things.append(0)things.append(0.0)things.append(42)things.append(3.14159)things.append("hello")things.append((3.0, 5.0))things.append(Student(name: "Tina", age: 10, school: "四川师范大学"))things.append({ (name: String) -> String in "Hello, \(name)" })print("\n")for thing in things { switch thing { case 0 as Int: print("zero as an Int") case 0 as Double: print("zero as a Double") case let someInt as Int: print("an integer value of \(someInt)") case let someDouble as Double where someDouble > 0: print("a positive double value of \(someDouble)") case is Double: print("some other double value that I don't want to print") case let someString as String: print("a string value of \"\(someString)\"") case let (x, y) as (Double, Double): print("an (x, y) point at \(x), \(y)") case let stu as Student: print("a student name: '\(stu.name)', age: \(stu.age), school: \(stu.school)") case let stringConverter as (String) -> String: print(stringConverter("Michael")) default: print("something else") }}
原则上若能够使用具体的数据类型,则尽量不要使用AnyObject类型,更要少考虑使用Any类型。从集合取出这些实例时,请尽可能地将AnyObject或Any类型转换为特定类型,然后在进行接下来的操作
- 类 的继承2
- 类继承2
- 类继承、虚继承
- JS继承-类继承
- java继承2——类与继承(转)
- javascript 类的继承2
- 继承、父子类、单继承、多继承
- C++ 类继承/虚继承/多重继承
- [Javascript] 继承 (原型继承, 类继承)
- 继承类
- 类继承
- 继承类
- 继承类
- 类继承
- 类继承
- 类继承
- 类继承
- 类继承
- 如何更改Linux中默认的openjdk为自己安装的JDK
- 渗透测试工具sqlmap基础教程
- 在分类中如何处理训练集中不平衡问题
- JAVA学习笔记(2)
- 团队程序设计天梯赛 L3-011. 直捣黄龙(dijkstra+搜索)
- 类继承2
- 链表——总结
- 每日学习20170405--使用slick对DB同步访问
- 无向图的邻接矩阵创建表示
- Java垃圾回收机制【经典总结】
- 20170405_Linux的引导流程解析
- javascript学习笔记--第一课:基础
- 第七周(Dynamic Programming)
- EasyUI异步分页