属性

属性是依赖于某个特定的类、结构体或者枚举类型的值。Swift有两种属性:存储类型和计算类型。其中存储类型可以作为实例的一部分存放变量或者常量的值,而计算类型的属性值是通过运算的来的。计算类型的属性可以在类、结构体和枚举类型中出现,但存储类型只可能出现在类和结构体类型中。

属性一般依赖于一个特定类型的实例,但是也可以依赖于类本身。依赖于类型本身的属性称为类型属性。

可以定义属性观察者来监督属性值的改变,从而作出响应。对集合不明白的看集合类型-数组详解

存储属性

常量属性let的值在初始化后不能在改变,而变量属性var的值可以随时更改。

struct   FixedLengthRange   {
     var   firstValue :   Int
     let  length :   Int
}
 
var   rangeOfThreeItems   =   FixedLengthRange ( firstValue :   0 ,   length :   3 )
rangeOfThreeItems . firstValue   =   6


结构体常量的存储属性

如果一个结构体实例被赋值给一个常量,则这个实例所拥有的存储类型的属性都不能在改变,包括变量属性在内。

let  rangeOfFourItems   =   FixedLengthRange ( firstValue :   0 ,   length :   4 )
rangeOfFourItems . firstValue   =   6
//编译错误,firstValue的值不能改变

延时存储属性

延时存储属性的初始值直到第一次使用的时候才进行计算,在声明时通过@lazy进行标记。

提示
一定要将延时存储属性声明为变量(var),因为它的初始值可能会在实例初始化完成后才有,而常量属性一般在实例初始化完成之前就会有值。

当属性的初始值依赖于外部银子,并且该因子的值在实例初始化完成之前不确定时,延时属性非常有用。如果属性初始化时需要进行大量的计算,也可以考虑使用延时属性。

下面是延时属性的示例:

class   DataImporter   {
     /*
    DataImporter是一个从外部文件导入数据的类。假设它需要花费较多的时间进行初始化
    */
     var   fileName   =   "data.txt"
     //DataImporter类的数据导入功能
}
 
class   DataManager   {
     @ lazy  var   importer   =   DataImporter ( )
     var   data   =   String [ ] ( )
     //DataManager类提供数据管理功能
}
 
let  manager   =   DataManager ( )
manager . data   +=   "Some data"
manager . data   +=   "Some more data"
//DataImporter实例还没有创建

只有问DataManager的importer属性时才会去创建这个对象。

println ( manager . importer . filename )
//创建importer属性并打印“data.txt"


存储属性与实例变量

Objective-C类的对象可以使用属性或者实例变量来存储值。Swift中并没有所谓的实例变量,而是将它们统一为属性了,这样使得属性的声明更加简化。

计算属性

除了存储属性外,类、结构体和枚举类型还可以定义计算属性。这些计算属性并不能够存储值,而是通过getter方法和可选的setter方法来间接的获取和设置其它属性和值。

struct   Point   {
     var   x   =   0.0 ,   y   =   0.0
}
 
struct   Size   {
     var   width   =   0.0 ,   height   =   0.0
}
 
struct   Rect   {
     var   origin   =   Point ( )
     var   size   =   Size ( )
     var   center :   Point   {
         get   {
             let  centerX   =   origin . x   +   ( size . width   /   2 )
             let  centerY   =   origin . y   +   ( size . height   /   2 )
             return   Point ( x :   centerX ,   y :   centerY )
         }
 
         set ( newCenter )   {
             origin . x   =   newCenter . x   -   ( size . width   /   2 )
             origin . y   =   newCenter . y   -   ( size . height   /   2 )
         }
     }
}
var   square   =   Rect ( origin :   Point ( x :   0.0 ,   y :   0.0 ) ,
                     size :   Size ( width :   10.0 ,   height :   10.0 ) )
let  initialSquareCenter   =   square . center
square . center   =   Point ( x :   15.0 ,   y :   15.0 )
println ( "square.origin is now at ((square.origin.x), (square.origin.y))" )
//打印”square.origin is now at (10.0, 10.0)“

这个例子定义了三个结构体来表示几何形状:

  • Point封装了(x, y)坐标。
  • Size封装了宽度和高度。
  • Rect用坐标原点和大小定义一个矩形。

其中Rect结构体还提供了一个center的计算属性。这个属性的值是由矩形的origin和size属性决定的,它本身并不需要存储信息。但是改变center的值,会间接的修改矩形的其它属性。