嵌套类型(Nested Types)
这个概念就是把一个类(结构体、枚举类)的定义放到一个类类(结构体、枚举类)的里面。
这个嵌套可以随便嵌套。可以在结构体里面定义类,类里面定义枚举类,枚举类里面定义结构体等等。
随便一个没意思的例子,访问方法也给出来了。使用点语法就可以了。
enum A {
struct B {
var num = 1
class Q {
}
class C {
var cc = 2
enum AA {
case d,e
}
class CCC {
}
}
}
}
print(A.B.C.AA.d) //d
print(A.B.C().cc) //2
类型判断符 is
使用is可以用来判断一个实例是否是某个类或是某个类是子类。返回一个Bool值。十分简单,看例子。
class Fruit {
}
class Apple : Fruit{
func eatApple() {
print("ear apple")
}
}
class Pear: Fruit {
func eatPear() {
print("eat pear")
}
}
var array = [Fruit(),Apple(),Pear()]
for item in array {
print(item is Apple)
}
//打印
//false
//true
//false
var f = Fruit()
var a = Apple()
var p = Pear()
print(a is Apple) //警告说 肯定返回 true
print(a is Fruit) //警告说 肯定返回 true
print(p is Apple) //警告说 肯定返回 false
print(f is Apple) //打印false
这as? as! 两个运算符可以将一个实例尝试转换为另外一个类的实例。一般是用在将一个父类变量的转换为一个子类变量。比如下面代码
var fruit: Fruit = Pear()
先来开开这句代码,我们把一个变量声明为了Fruit类型,但是赋值的时候给的却是Fruit的子类Pear。这个时候并不会报错。这种用一个父类类型的变量指向一个子类的做法称为多态。多态在面向对象编程里面有很重要的作用。这里不展开讲。
因为fruit变量声明为了Fruit类型,即使它实际引用的实例是Pear类,但是现在还是不能通过它来调用Pear类引入的属性或方法。尽管这个实例确实是拥有这些属性和方法。为了去访问这些存在的属性和方法,我们就要采用类型下转换,将这个fruit的变量转换为一个pear的变量。
var pear = fruit as? Pear
上面的代码使用as?,尝试将这个fruit转为一个Pear类型的变量。这里因为fruit引用的实例就是Pear,所以是可以转换成功。成功后返回了一个Pear的可选类型给变量pear。但是如果转换失败,返回的是一个nil。比如你尝试将一个Apple实例转换为一个Pear,或者将一个Fruit实例转换为它的子类都会失败。
补充一点,如果对上面的fruit变量使用is判断是否是Pear类,返回的是true。
as!和as?的区别就是强制解包了。学了那么多,应该可以猜到。
最后在介绍这个比较诡异的as之前,看看Any和AnyObject这两个类型。
Any代表任何类型的实例,包括了函数类型。
AnyObject代表任何类的实例。
现在介绍as的用法,现在只发现as能用在switch中,用来判断变量是否是某个类型
func f1() -> Int{
return 1
}
var b = {var i=0; i++}
var array: [Any] = [f1,b,fruit,Fruit(), Apple(), Pear(), Animal(), (2,3), (4,5)]
for (index, item) in array.enumerate() {
switch item {
case let item2 as Apple :
print("index\(index) is \(item2)")
case is Pear:
print("index\(index) is pear")
case let (2,y) as (Int, Int) where y > 2:
print("index\(index) is tuple y =",y)
case is (Int,Int):
print("index\(index) is (Int,Int) ",item)
case let f as Void->Void:
print("index\(index) is Void->Void ",item)
default:
print("index\(index) is default",item)
}
}
//打印
//index0 is default (Function)
//index1 is Void->Void (Function)
//index2 is pear
//index3 is default SwiftTest.Fruit
//index4 is SwiftTest.Apple
//index5 is pear
//index6 is default SwiftTest.Animal
//index7 is tuple y = 3
//index8 is (Int,Int) (4, 5)
你会发现其实,is 和 as 的效果是一样的。as比is多的就是将一个tuple可以再次解包出元素,并且再次匹配元素,同时还可以加上where做判断。比如上面的第三个case语句。会判断这个item是否是(Int,Inte)类型,然后解包tuple,判断第一个元素是否为2,如果是2,还会判断第二个元素是否大于2.只有这三个条件都符合才会匹配这个case。