对象类型(类、结构体与枚举)都有一个共同的重要特性:它们可以实例化。事实上,在声明一个对象类型时,你只不过是定义了一个类型而已。实例化类型则是创建该类型的一个实例。
比如,我可以声明一个Dog类并为其添加一个方法:
class Dog { func bark { print("woof") }}
但程序中实际上并没有任何Dog对象。我只不过是描述了Dog类型。要想得到一个实际的Dog,我需要创建一个。
图1-1:创建实例并调用实例方法
创建一个类型为Dog类的实际的Dog对象的过程就是实例化Dog的过程。结果就是一个全新的对象——一个Dog实例。
在Swift中,实例可以通过将对象类型名作为函数名并调用该函数来创建。这里使用了圆括号。在将圆括号附加到对象类型名时,你实际上向该对象类型发送了一条非常特殊的消息:实例化自身!
现在来创建一个Dog实例:
let fido = Dog
上述代码蕴涵着很多事情!我做了两件事:实例化了Dog,得到一个Dog实例;还将该Dog实例放到了名为fido的盒子中——我声明了一个变量,然后通过将新的Dog实例赋给它来初始化该变量。现在fido是一个Dog实例。(此外,由于使用了let,因此fido将总是指向这个Dog实例。我可以使用var,但即便如此,将fido初始化为一个Dog实例依然表示fido将只能指向某个Dog实例)。
既然有了一个Dog实例,我可以向其发送实例消息。你觉得会是什么呢?它们是Dog的属性与方法!比如:
let fido = Dogfido.bark
上述代码是合法的。不仅如此,它还是有效的:它会在控制台中输出"woof"。我创建了一个Dog,并且让其吼叫(如图1-1所示)!
这里有一些重要的事情要说明一下。在默认情况下,属性与方法是实例属性与实例方法。你不能将其作为消息发送给对象类型本身;只能将这些消息发送给实例。正如下面的代码所示,这么做是不合法的,无法编译通过:
Dog.bark // compile error
可以声明一个函数bark,使得Dog.bark()调用变成合法调用,不过这是另外一种函数(类函数或是静态函数)。如果声明了这样的函数就可以这么调用了。
属性也一样。为了说明问题,我们为Dog增加一个name属性。到目前为止,每一个Dog都有一个名字,这是通过为变量name赋值而得到的。不过该名字并不属于Dog对象本身。name属性如下所示:
class Dog { var name = ""}
这样就可以设置Dog的name了,不过需要是Dog的实例:
let fido = Dogfido.name = "Fido"
还可以声明属性name,使得Dog.name这种写法变成合法的,不过这是另外一种属性——类属性或是静态属性——如果这么声明了,那就可以这样使用。