7.1 类与结构体的定义
在生活中,人们将拥有相似属性和行为的事物归为一类,生物被分为动物、植物和微生物等,动物和植物又会进一步分门别类,如鸟、兽、鱼、虫等。编程中的类也有相似的意义,一个基类可以派生出各种子类。在Swift语言中,结构体是功能仅逊于类的数据结构,其也可以描述拥有某些属性和行为的事物,只是它的实现机制和类有着本质的区别,应用场景也有所不同。
7.1.1 结构体
在编程中,结构体是用于描述一种事物的结构。在Objective-C语言中,结构体中只可以定义属性,而不能定义方法;而在Swift语言中,结构体和类十分相似,其中既可以定义属性,又可以定义方法,但其不像类一样具有继承的特性。
在Swift语言中,使用struct关键字来定义结构体,结构体中可以声明变量或者常量作为结构体的属性,也可以创建函数作为结构体的方法,结构体使用点语法来调用其中的属性和方法。使用Xcode开发工具创建一个名为ClassAndStruct的Playground文件,在其中编写一个汽车的结构体,示例代码如下:
上面的代码中示例的结构体模拟了汽车这样的事物,并提供了3个属性,分别代表汽车的价格、品牌、油量,还提供了两个方法,分别表示汽车行路与加油的行为。在创建结构体后,结构体会默认生成一个构造方法供开发者使用,开发者可以在构造方法中完成对结构体的实例化,示例代码如下:
以上示例代码通过结构体来模拟现实生活中的汽车,需要注意,Swift语言中的数据类型分为值类型和引用类型。结构体、枚举以及前面读者接触到的除类以外的所有数据类型都属于值类型,只有类是引用类型的。值类型数据和引用类型数据最大的区别在于当进行数据传递时,值类型总是被复制,而引用类型不会被复制,引用类型是通过引用计数来管理其生命周期的。关于引用计数与内存管理,后面章节会专门介绍。读者在这里需要注意,如果值类型有数据传递,原来的实例会被复制一份,修改新的实例并不能修改原始的实例,以Car结构体为例:
从上面代码的打印信息可以看出,car实例与car2实例分别独立。
7.1.2 类
类是较结构体更加高级的一种数据类型,编程中的所有复杂数据结构都是通过类来模拟的。简单理解,类是编程世界中万物的抽象,使用类可以模拟万物的对象。以射击类游戏为例,游戏中的主角、武器、道具、敌人、子弹等都是类。
Swift语言中的类使用关键字class来声明,使用类的方式模拟汽车类型,示例代码如下:
分析上面创建ClassCar类的代码可以发现,类与结构体创建属性与方法的代码基本一样。不同的是,在结构体中开发者并不需要提供构造方法,结构体会根据属性自动生成一个构造方法,而类则要求开发者自己提供构造方法,在init()构造方法中,需要完成对类中所有属性的赋值操作。
创建类实例、访问类实例属性的方法,示例如下:
可以看出,类和结构体一样,也是通过点语法来完成属性方法的访问的。和结构体不同的是,类是引用类型,对类实例进行数据传递时并不会产生复制行为。因此,如果将类实例传递给新的变量,修改新的变量会影响原始变量,示例如下:
正是由于类的这种特性,在编程中,同一个类实例可以被多处引用共享。