Swift学习笔记18——嵌套类型(Nested Types)和类型转换(Type Casting)

嵌套类型(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! ,下转换判断符as

这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。


你可能感兴趣的:(Swift学习笔记)