首页 » iOS编程基础:Swift、Xcode和Cocoa入门指南 » iOS编程基础:Swift、Xcode和Cocoa入门指南全文在线阅读

《iOS编程基础:Swift、Xcode和Cocoa入门指南》1.12 为何使用实例

关灯直达底部

虽然没有实例这个事物,不过一个对象类型本身就是个对象。之所以这么说是因为我们可以向对象类型发送消息:可以将对象类型看作命名空间,并显式进入该命名空间中(如Manny.Klass)。此外,既然存在类成员与静态成员,我们可以直接调用类、结构体或枚举类型的方法,还可以引用类、结构体或枚举类型的属性。既然如此,实例还有存在的必要吗?

答案与实例属性的本质有关。实例属性的值的定义与特定的实例有关,这正是实例真正的用武之地。

再来看看Dog类。我为它添加了一个name属性和一个bark方法;请记住,它们分别是实例属性与实例方法:


class Dog {    var name = ""    func bark {        print("woof")    }}  

Dog实例刚创建出来时name是空的(一个空字符串)。不过其name属性是个var,因此一旦创建了Dog实例,我们就可以为其name赋予一个新的String值:


let dog1 = Dogdog1.name = "Fido"  

还可以获取Dog实例的name:


let dog1 = Dogdog1.name = "Fido"print(dog1.name) // "Fido"  

重要之处在于我们可以创建多个Dog实例,两个不同的Dog实例可以拥有不同的name属性值(如图1-2所示):


let dog1 = Dogdog1.name = "Fido"let dog2 = Dogdog2.name = "Rover"print(dog1.name) // "Fido"print(dog2.name) // "Rover"  

注意,Dog实例的name属性与Dog实例所赋予的变量名之间没有任何关系。该变量只不过是一个盒子而已。你可以将一个实例从一个盒子传递给另一个。不过实例本身会维护自己的内在统一性:


let dog1 = Dogdog1.name = "Fido"var dog2 = Dogdog2.name = "Rover"print(dog1.name) // "Fido"print(dog2.name) // "Rover"dog2 = dog1print(dog2.name) // "Fido"  

上述代码并不会改变Rover的name;它改变的是dog2盒子中的狗,将Rover替换成了Fido。

基于对象编程的威力现在开始显现出来了。有一个Dog对象类型,它定义了什么是Dog。我们对Dog的声明表示任何一个Dog实例都有一个name属性和一个bark方法。不过每个Dog实例都有自己的name属性值。它们是不同的实例,分别维护着自己的内部状态。因此,相同对象类型的多个实例的行为都是类似的:Fido与Rover都可以吼叫,如果向它们发送bark消息它们就会这么做,但它们是不同的实例,可以有不同的属性值:Fido的name是"Fido",而Rover的name是"Rover"。

图1-2:具有不同属性值的两只狗

(对于数字1与2来说同样如此,不过事实却并不是那么显而易见。Int是一个value属性。1是一个Int,其值是1,2表示值为2的Int。不过,这一事实在实际开发中却没那么有趣,因为你显然不会改变1的值!)

实例是其类型的实例方法的反映,但这并非全部;它还是实例属性的集合。对象类型负责实例所拥有的属性,但对这些属性的值并不是必需的。当程序运行时,值可以发生变化,并且只会应用到特定的实例上。实例是特定属性值的集合。

实例不仅要负责值,还要负责属性的生命周期。假设我们创建了一个Dog实例,并为其name属性赋予了值"Fido"。那么只要我们没有使用其他值替换掉其name值并且该实例处在存活状态,那么该Dog实例就会一直持有字符串"Fido"。

简而言之,实例既包含代码又包含数据。代码来自于实例的类型,并且与该类型的所有其他实例共享,不过数据只属于该实例本身。只要实例存在,其数据就一直存在。在任意时刻,实例都有一个状态——自身属性值的完整集合。实例是维护状态的一个设备,它是数据的一个存储箱。