每天学一点Swift----面向对象下(四)

三.多态

1. Swift引用变量有两个类型:一个编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,编译器只认每个变量的编译时类型;运行时类型由实际赋给该变量的实例决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态。

2. Swift中的多态和Java中的多态的概念是一样的,即:父类引用指向子类对象。

3.多态的定义:相同类型的变量或调用同一个方法时呈现出多种不同的行为特征,这就是多态。

4.使用is运算符检查类型:is运算符的前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类(也可以是协议,可以把协议理解成一种特殊的类),它用于判断前面的引用变量是否引用后面的类,或者其子类、实现类的实例。如果是,则返回true,否则返回false。----等同于Java中isinstanceof运算符。

5.使用as运算符向下转型:在Swift程序中,引用变量只能调用其编译时类型的方法,而不能调用其运行时类型的方法,即使它实际所引用的实例确实包含该方法。如果需要让这个引用变量调用其运行时类型的方法,则必须把它强制转换为实际的类型,这种强制转换也被称为向下转型。

6.向下转型时需要借助于向下转型运算符。Swift提供了两个向下转型运算符:

(1)as:强制将运算符前面的引用变量转换为后面的类型,如果转换失败,程序将导致运行时错误。

(2)as?:可选形式的向下转换。该运算符也试图将运算符前面的引用变量转换为后面的类型。该运算符总返回一个可选值,如果转换成功,则可选值中包含转换结果;如果转换失败,则可选值中包含nil。

7.向下转换只能是在具有继承关系的两个类型之间进行,如果是两个没有任何继承关系的类型,则无法进行类型转换,否则编译时就会出现错误。如果试图把一个父类引用变量转换成子类类型,则该变量实际引用的实例必须是子类实例才行(即编译时类型为父类类型,而运行时类型为子类类型),否则就会报错。

8.考虑到进行强制类型转换时可能会出现异常,因此进行类型转换之前可先通过is运算符进行判断是否可以成功转换,从而避免出现运行时错误,这样可以保证程序更加健壮。

9.当把子类实例赋值给父类引用时,被称为向上转型,这种转型总是成功的。

10.如果不想在进行向下转型前用is进行判断,则可以借助于as?执行可选形式的向下转换,由于as?转型返回的是可选值,因此程序可能还需要进行可选绑定。举个栗子:

class Fruit

{

var name : String

var weight : Double

init(name : String, weight : Double)

{

self.name = name

self.weight = weight

}

}

class Apple : Fruit

{

var color : String

init(name : String, weight : Double, color : String)

{

self.color = color

super.init(name : name, weight : weight)

}

}

class Grape : Fruit

{

var sugarRate : Double

init(name : String, weight : Double, sugarRate : Double)

{

self.sugarRate = sugarRate

super(name : name, weight : weight)

}

}

//使用数组保存4个水果

var fruits:[Fruit] = {

Apple(name : "红富士", weight : 1.8, color : "粉红")

Apple(name : "花牛过", weight : 2.2, color : "红色")

Grape(name : "巨峰", weight : 1.2, sugarRate : 0.32)

Grape(name : "加州提子", weight : 2.0, sugarRate : 0.40)

}

//由于fruits的类型是Fruit,因此程序只知道该数组元素是Fruit

for f in fruits{

//此处先使用as?执行向下转型,返回可选值,然后使用可选值

if let ap = f as? Apple{

print("\(ap.name)苹果的颜色是:\(ap.color)")

}

else if let gp = f as? Grape{

print("\(gp.name)葡萄的糖分是:\(gp.sugarRate)")

}

}

11. Swift为不确定类型提供了两种特殊的类型别名:

(1)AnyObject:可代表任何类的实例

(2)Any:可代表任何类型,包括Int,Double等值类型。。。。。。

12.举个栗子:继续以上面的Fruit,Apple,Grape为例

var anyArray:[Any] = {

"swift", "26", ["ios", "java", "oc", 89, 12.34], Fruit(name : "fruit", weight : 2.2),

Apple(name : "apple", weight : 3.3, color : "color")]

}

//遍历元素为Any的数组

for element in anyArray

{

//尝试将数组元素强制转换为Fruit,然后执行可选绑定

if let f = element as? Fruit

{

print("Fruit")

}

}

//定义元素类型为AnyObject的数组,该数组的元素只能是对象

var anyObjectArray : [AnyObject] = [

Fruit(name : "fruit", weight : 2.2),

Apple(name : "apple", weight : 3.3, color : "color")

]

//这行代码将会导致错误

anyObjectArray.append("swift")

上面定义了一个元素类型为AnyObject的数组,该数组只能装对象,不能装其他数据,因此上面的最后一行代码报错。

你可能感兴趣的:(每天学一点Swift----面向对象下(四))