[Swift]多态类型转换以及不确定类型
来源:互联网 发布:淘宝同城的怎么搜索 编辑:程序博客网 时间:2024/05/16 07:04
1. Swift的多态:
1) 和其它语言多态描述一致,都是用父类指针或引用(这里的父类是指祖先类)指向子类的实例,然后在子类中覆盖父类的方法,利用该父类引用调用相同的方法而产生不同的行为;
2) Swift的多态类型转换:和普通的类型转换不一样,普通的类型转换是指一般意义上的强制类型转换,但是强制类型转换不能发生在类型之间,如果使用"类名(转换对象)"则会触发相应类的构造器而不能达到转换类型的效果,因此Swift的类型转换只能发生在可以转换的两个对象之间,对于不能转换的两个对象会在编译阶段或是运行阶段报错;
Swift专门为多态之间的类型转换提供了解决方案,它的机制有严格的规则要求,首先必须要让一个父类的引用指向一个其子类的实例(这个是大前提),然后可以利用is运算符来判断该引用指向的实例是否属于某个子类,同时可以使用as运算符将该引用指向的实例正确地转化成相应的子类类型,这种转换也称为向下转换(即先将子类实例用父类包装,等到使用时再把它彻底扩展成子类);
这就好比有一个动物的序列,序列中有各种各样的动物,起初不知道该序列里每个动物都属于哪一类(比如猫科、鸟类等),但大前提是这些子类(猫科、鸟类、爬行类等都属于动物这个父类的子类),因此起初可以将这整个序列里的元素都当成动物这个基类来看待(is-a的关系,C++中解释继承关系的经典形容),然后逐个取出序列里的元素判断其具体属于哪个子类(是猫科呢还是鸟类等),这是就使用is来判断,如果确实属于猫科,则使用as操作符将一般性的动物类的猫转化成具体的猫科类,这样就可以使用猫所具有但动物所不具有的功能(基类引用只能访问基类的属性以及实现多态,但不能访问子类的新增部分);
3) 首先看一个多态的例子:
class A { func show() { println("A") }}class B: A { override func show() { println("B") }}var a = A()a.show() // Aa = B()a.show() // B
2. Swift的多态类型转换:
1) 即is和as两个操作符的运用;
2) 还是强调那句,这两个操作符的使用必须严格遵守之前讲过的规则:必须要让一个父类的引用指向一个其子类的实例,然后再对该引用用is判断是否属于某个具体的子类或用as将其转换成某个具体的子类类型;
3) is的使用:
class A { }class B: A { }class C: A { }var cnt_b = 0, cnt_c = 0// 都是A的子类因此发生多态,obj的类型为Alet obj = [B(), B(), C(), C(), B()]for item in obj { if item is B { // 注意is的左边的类型必须是右边类型的父类!否则就报错! cnt_b++ } else if item is C { cnt_c++ }}println("cnt_c = \(cnt_c), cnt_b = \(cnt_b)") // 2 3var obj_a = A()// 只能判断一个用父类引用指向的子类实例是否属于某个子类// 不能用于判断非以上关系的实例是否属于某个类// println(obj_a is A) // Bad! 必须是父类引用指向子类实例,指向自己也不能判断,会直接报错的!// println(B() is B) // Bad! 理由同上,不能判断自己是否属于自己的类型// println(obj_a is String) // Bad!只能用于多态引用class D: B { }var d: A = D()println(d is D) // OK! 多层继承的多态引用也行!4) as的使用(接上例代码):
cnt_b = 0cnt_c = 0for item in obj { if let obj_b = item as? B { // 同样as左侧的类型必须是右侧的父类,同样两侧的类型不能相同 cnt_b++ } else if let obj_c = item as? C { cnt_c++ }}println("cnt_c = \(cnt_c), cnt_b = \(cnt_b)") // 2 3!使用as时如果能转换则成功,如果不能则会抛出运行时异常,为了不抛出异常在as后加?可以起到和可选链一样的功能,只返回nil而不会那么暴力地抛出异常,同时配合let绑定可以达到一举两得的效果,相当于is判断的同时也同时实现了类型转换!
3. 两种不确定类型——Any和AnyObject:
1) 注意Swift的不确定类型和Java的Object类不一样,它并不是所有类的基类,可以说它们并不是类,而只是一种不确定类型(类似C语言的void类型);
2) AnyObject可以接受任何类类型数据,而Any可以接受任意类型的数据(包括AnyObject和基本类型),由于基本类型不是类类型,因此可见这两种不确定类型并不是类类型;
3) 虽然不是类类型,但是可以使用is和as操作符,比如0 is Int或0 as Double,其实这里的,其实这里的is和as都使用Any进行重载;
4) 整个数组整体转换(前提是数组中所有元素类型必须一样):形式是AnyOrAnyObjectArray as [SpecificType],这样就可以返回一个转换好的[SpecificType]数组了,但是不能使用可选符号?进行保护!
class A { }class B { }var arr: [AnyObject] = [B(), B(), B(), B(), B(), B()]for item in arr as [B] { // 这里不能写成as?或[B?],否则会报错 // 数组整体转换必须是强制而不能使用可选?,这可能是Swift不足的地方,因此这里强制要求arr中所有元素类型一致,否则就抛出运行时异常,因为不能用?保护 println("is B")}5) 一个Any的例子:
class A { }class B { }var arr: [Any] = [1, 3.923, A(), "xlkfds", B(), B(), 9 / 12, A()]for item in arr { if let a = item as? A { println("A") } else if let b = item as? B { println("B") }// else if let c = item as? Any { // 不能转换成Any或AnyObject自己本身,编译器从语法上不允许这样做!// println("haha")// }} // A B B A
4. 类型转换在switch中的应用:
1)
- [Swift]多态类型转换以及不确定类型
- Swift的类型推断会不会造成类型不确定的困扰?
- Swift类型转换
- 18.Swift-类型转换
- Swift-类型转换
- swift 类型转换
- Swift 对象类型转换
- swift 对象类型转换
- Swift-类型转换
- swift 类型转换
- 细说Swift类型转换
- swift-9 类型转换
- Swift类型转换
- Swift AnyObject 类型转换
- swift-类型转换
- Swift 类型转换
- Swift Assertion断言/类型别名/类型转换
- Swift(十九、类型转换&嵌套类型)
- Thrift安装和试用
- Problem H: 魔方阵
- Android ListView 获取高度
- TextView长按复制实现方法小结
- iOS应用安全风险及加密解决措施
- [Swift]多态类型转换以及不确定类型
- android 检测Service是否正在运行
- Study JavaScript《parseInt使用》
- Java 实现抽象工厂模式
- calltree 在ubuntu(12.04)上的编译 ___附 已编译+源码包
- 关于linux进程间的close-on-exec机制
- 鸟哥释疑——关于变量的删除
- android Button 的按下和抬起事件监听
- Android中SQLite应用详解