首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Swift教程之属性详解

Swift教程之属性详解

属性是描述特定类、结构或者枚举的值。存储属性作为实例的一部分存储常量与变量的值,而计算属性计算他们的值(不只是存储)。计算属性存在于类、结构与枚举中。存储属性仅仅只在类与结构中。
属性通常与特定类型实例联系在一起。但属性也可以与类型本身联系在一起,这样的属性称之为类型属性。
另外,可以定义属性观察者来处理属性值发生改变的情况,这样你就可以对用户操作做出反应。属性观察者可以被加在自己定义的存储属性之上,也可以在从父类继承的子类属性之上。
1、存储属性
最简单的情形,作为特定类或结构实例的一部分,存储属性存储着常量或者变量的值。存储属性可分为变量存储属性(关键字var描述)和常量存储属性(关键字let描述)。
当定义存储属性时,你可以提供一个默认值,这些在“默认属性值”描述。在初始化过程中你也可以设置或改变存储属性的初值。这个准则对常量存储属性也同样适用(在“初始化过程中改变常量属性”描述)
下面的例子定义了一个叫FixedLengthRange的结构,它描述了一个一定范围内的整数值,当创建这个结构时,范围长度是不可以被改变的:

[url=]复制代码[/url] 代码如下:

struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// the range represents integer values 0, 1, and 2
rangeOfThreeItems.firstValue = 6
// the range now represents integer values 6, 7, and 8

FixedLengthRange的实例包含一个名为firstValue的变量存储属性和名为length的常量存储属性。以上的例子中,当范围确定,length被初始化之后它的值是不可以被改变的
常量结构实例的存储属性
如果你创建一个结构实例,并将其赋给一个常量,这个实例中的属性将不可以被改变,即使他们被声明为变量属性
[url=]复制代码[/url] 代码如下:

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// this range represents integer values 0, 1, 2, and 3
rangeOfFourItems.firstValue = 6
// this will report an error, even thought firstValue is a variable property

因为rangeOfFourItems是一个常量(let),即便firstValue是一个变量属性,它的值也是不可以被改变的
这样的特性是因为结构是值类型。当一个值类型实例作为常量而存在,它的所有属性也作为常量而存在。
而这个特性对类并不适用,因为类是引用类型。如果你将引用类型的实例赋值给常量,依然能够改变实例的变量属性。
Lazy Stored Properties(懒惰存储属性?)
懒惰存储属性是当它第一次被使用时才进行初值计算。通过在属性声明前加上@lazy来标识一个懒惰存储属性。
注意
必须声明懒惰存储属性为变量属性(通过var),因为它的初始值直到实例初始化完成之后才被检索。常量属性在实例初始化完成之前就应该被赋值,因此常量属性不能够被声明为懒惰存储属性。
当属性初始值因为外部原因,在实例初始化完成之前不能够确定时,就要定义成懒惰存储属性。当属性初始值需要复杂或高代价的设置,在它需要时才被赋值时,懒惰存储属性就派上用场了。
下面的例子使用懒惰存储属性来防止类中不必要的初始化操作。它定义了类DataImporter和类DataManager:

[url=]复制代码[/url] 代码如下:

class DataImporter {
/*DataImporter is a class to import data from an external file.     The class is assumed to take a non-trivial amount of time to initialize.*/
var fileName = "data.txt"
// the DataImporter class would provide data importing functionality here
}
class DataManager {
@lazy var importer = DataImporter()
var data = String[]()
// the DataManager class would provide data management functionality here
}
let manager = DataManager()
manager.data += "Some data"
manager.data += "Some more data"
// the DataImporter instance for the importer property has not yet been created

类DataManager有一个称为data的存储属性,它被初始化为一个空的String数组。虽然DataManager定义的其它部分并没有写出来,但可以看出DataManager的目的是管理String数据并为其提供访问接口。
DataManager类的部分功能是从文件中引用数据。这个功能是由DataImporter类提供的,这个类需要一定的时间来初始化,因为它的实例需要打开文件并见内容读到内存中。
因为DataManager实例可能并不需要立即管理从文件中引用的数据,所以在DataManager实例被创建时,并不需要马上就创建一个新的DataImporter实例。这就使得当DataImporter实例在需要时才被创建理所当然起来。
因为被声明为@lazy属性,DataImporter的实例importer只有在当它在第一次被访问时才被创建。例如它的fileName属性需要被访问时:
[url=]复制代码[/url] 代码如下:

println(manager.importer.fileName)
// the DataImporter instance for the importer property has now been created
// prints "data.txt

存储属性与实例变量
如果你使用过Objective-C,你应该知道它提供两种方式来存储作为类实例一部分的值与引用。除了属性,你可以使用实例变量作为属性值的后备存储
Swift使用一个单一属性声明来统一这些概念。一个Swift属性没有与之相符的实例变量,并且属性的后备存储也不能直接访问。这防止了在不通上下文中访问值的混淆,并且简化属性声明成为一个单一的、最终的语句。关于属性的所有信息-包含名称、类型和内存管理等-作为类型定义的一部分而定义。
继承事业,薪火相传
返回列表