属性是特定类、结构或枚举的相关值,属性根据作用域不同分为实例属性与类型属性,还可以根据是否存储分为存储属性和计算属性。

1.1 实例属性

为一个类、结构或枚举定义的属性默认属于实例属性,即该属性属于为该类型创建的不同实例,不同实例具有属性的不同拷贝。每次当你创建了一个特定类型的新的实例,它总有一组自己的属性,即每个实例带有自己的一组属性。

实例属性可以是存储属性和计算属性,可以为类和结构的实例定义存储属性和计算属性,而枚举实例只能定义计算属性。

另外所有类型的实例都有一个称为self的隐含的属性,相当于实例本身。可以在实例方法内使用隐含的self属性来引用当前的实例。如:

func increment() {

self.count++

// 这里使用self是多余的,count通常引用的就是当前实例的属性,除非//方法increment包含一个与count名字相同的参数。

}

1.2  类型属性

你能为类、结构或枚举类型定义称作类型属性的属性。

类型属性对于那种类型的所有实例,仅有该属性的一份拷贝。

类型属性为特定类型的所有实例定义一个统一的值,例如所有实例都能使用的一个常量属性(与C语言的静态常量类似),或者类型的所有实例都能用的一个存储变量属性(相当于C语言的静态变量)。

对于值类型(结构和枚举类型),你能为它们定义存储类型属性(可以是变量或者是常量)和计算类型属性,对于类,仅能为它们定义计算类型属性。  计算类型属性总是被声明为变量属性。

与C 和 Objective-C语言不同的是,类型属性是作为类型定义的一部分定义在类型定义的大括号内部,每个类型属性都属于它所支持的类型。

类型属性的定义语法为:用static关键字为值类型(结构类型和枚举类型)定义类型属性,使用class关键字为类定义类型属性。

由于类型本身没有一个初始化方法在初始化期间来为存储类型属性分配值,因此与实例的存储属性不同,你必须为类型的存储属性在定义时就指定一个默认值。

如下例所示:

struct SomeStructure {

static var storedTypeProperty
="Some value."

static var computedTypeProperty:Int
{

// return an Int value here

}

}

class SomeClass {

class var computedTypeProperty:Int
{

// return an Int value here

}

}

以上例子为名字为SomeStructure的结构类型定义了一个存储类型属性storedTypeProperty,并指定其默认值为"Some value.”,也定义了一个称为computedTypeProperty的计算属性。

名字为SomeClass的类定义了一个计算属性computedTypeProperty,计算属性必须声明为var类型。

与实例属性一样,类型属性也使用点语法进行查询和设置,例如:

println(SomeClass.computedTypeProperty)

SomeStructure.storedTypeProperty
="Another value.”

1.3、存储属性

一个 存储属性可以是一个常量或一个变量,并作为一个特定类或结构实例的一部分被存储。

一个实例的存储属性的定义语法与通常的常量和变量的定义语法相同,并也支持类型推断,只是存储属性在一个类型内部定义。

你能在存储属性定义时为其提供一个默认值,也能够在初始化期间设置和修改一个存储属性的初始值。常量属性在初始化设置后不能再被改变。

由于结构是值类型,如果你创建一个结构实例并分配它给一个常量,在该结构实例实例化后,你不能再修改他的属性,即使结构的属性是变量属性。

let rangeOfFourItems =FixedLengthRange(firstValue:0,length:4)

rangeOfFourItems.firstValue =6

// 这将报一个运行时错误

1.4 懒惰存储属性

一个懒惰存储属性是存储属性的特例,一个懒惰存储属性的初始化推迟到需要时进行 。你能在属性声明前加上一个@lazy 来指示该属性是一个懒惰存储属性。

你只能给变量属性声明为懒惰属性。由于常量属性在初始化完成之前必须包含一个值,因此不能声明一个常量属性作为懒惰属性,。

懒惰属性在某些情况下是有用的,如某个属性的的初始值依赖于某些外部因素,而这些外部因素在实例的初始化完成之前还不知道。或者属性的初始值需要复杂或者需要耗费大量计算来设置时。因此在这些情况为了性能考虑需要定义懒惰属性,以便推迟懒惰属性的初始化到需要时进行。

class DataImporter {

var fileName
="data.txt"

}

class DataManager {

@lazy var importer
=DataImporter()

var data
=String[]()

}

let manager =DataManager()

manager.data +="Some
data"

以上例子,由于DataManage实例的importer属性被标记为懒惰属性,因此DataManager实例化时该属性不被创建,只有在使用到该属性时,例如它的fileName被如下语句查询时才创建。

println(manager.importer.fileName)

1、5 计算属性

计算属性不实际存储一个值,计算属性通过提供一个getter方法和一个可选的setter方法来间接引出或设置其它属性和值。如:

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)

以上例子为类Rect定义了一个计算属性center,center的属性值由另外的属性origin和size计算确定,该例为center属性定义了两个定制的getter和setter方法,以便能够采用与存储属性相同的方法(点语法)来获取和设置计算属性的值。

如果计算属性的setter方法没有为新设置的值定义名字,默认采用newValue名字,如下例所示:

struct AlternativeRect
{

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 {

origin.x
=newValue.x - (size.width
/ 2)

origin.y
=newValue.y - (size.height
/ 2)

}

}

}

如果只为一个计算属性提供一个getter方法,而没有为其提供setter方法,则该计算属性称为只读的计算属性。只读的计算属性只返回值,但不能为其设置值,如果使用点语法为其设置值,则报一个运行时错误。

  • structCuboid
    {
  • varwidth
    = 0.0,height
    = 0.0,depth
    = 0.0
  • varvolume:Double
    {
  • returnwidth
    * height
    * depth
  • }
  • }
  • 以上为结构Cuboid定义了一个只读的计算属性,getter方法的get关键字也省略了。

由于计算属性的值是可变的,因此你必须声明计算属性(包括只读的计算属性)作为变量属性(var)。

1.6 属性观察者

属性观察者用来监视属性值的改变,并以特定的动作作为应答。

在每次属性的值被设置,即使新设置的值与属性的当前值相同,为属性定义的属性观察者也被调用。

你能在除了懒惰存储属性外的任意存储属性上增加属性观察者,也能通过类继承并重写继承的超类的属性在一个继承属性(无论存储属性或者是计算属性)上添加属性观察者。

需要注意你不需要为非继承的计算属性定义属性观察者,原因是它们能够直接在计算属性的设置方法中观察和应答属性值的变化。

你能在一个属性上选择定义如下两个观察者之一或全部。

willSet观察者在属性值被存储之前被调用,didSet观察者在新的属性值被存储后被立即调用。

如果你实现一个willSet观察者,新的属性值作为一个常量参数传递。你能作为willSet实现的一部分为该参数规定一个名字。如果你在实现中选择不写参数名字和括号,则使用默认的参数名字newValue。

相似地,实现一个didSet观察者,给它传送一个包含旧的属性值的常量参数,你也能为其命名你希望的参数名字,或者使用默认的参数名字oldValue。

willSet和didSet观察者在属性的首次初始化时不被调用,它们仅在属性的值在初始化完成后再被改变时才调用。

class StepCounter {

var totalSteps:Int
=0 {

willSet(newTotalSteps)
{

println("About
to set totalSteps to\(newTotalSteps)")

}

didSet {

if totalSteps
>oldValue  {

println("Added\(totalSteps
-oldValue) steps")

}

}

}

}

let stepCounter =StepCounter()

stepCounter.totalSteps =200

// About to set totalSteps to 200

// Added 200 steps

以上类StepCounter为totalSteps属性定义了两个观察者willSet和didSet,willSet观察者为参数定义了一个新的参数名字newTotalSteps,didSet观察者使用默认参数名字。如例子打印所示在属性totalSteps改变前后,两个观察者先后被调用。

1.7 全局和本地变量

全局变量是在任意函数、方法、闭包或类型的上下文外面定义的变量,本地变量是在一个函数、方法、闭包上下文内部定义的变量。

全局和本地变量是一个存储变量,用来存储一个能够设置或读取的特定类型的值。

你能够在全局和本地变量上定义计算变量和定义观察者。

为了性能上的优化考虑,全局变量和全局常量具有计算懒惰特性,与懒惰属性一样,其初始化推迟到需要时进行。

版权所有,转载时请清楚注明链接和出处,谢谢!

苹果新的编程语言 Swift 语言进阶(八)--属性的更多相关文章

  1. 苹果新的编程语言 Swift 语言进阶(四)--字符串和收集类型

    一.字符串( String  )和字符类型(Character) 字符串是一种字符的带次序的收集类型(相当于数组),字符是字符串中的元素. 在Swift 语言中,字符串是编码独立的Unicode字符的 ...

  2. 苹果新的编程语言 Swift 语言进阶(一)--综述

    Swift 是苹果开发和提供的供开发IOS 和OS X应用的一门新的语言.Swift语言基于C 和Objective-C语言,除了提供C 和Objective-C语言具有的所有语法功能外,为了编程方便 ...

  3. 苹果新的编程语言 Swift 语言进阶(三)--基本运算和扩展运算

    一 基本操作运算 1. 赋值操作 在Swift 中,能够使用赋值操作为一个常量或一个变量赋值,也能够使用多元组一次为多个常量或变量赋值. Swift 的赋值操作与其他语言最大的不同是赋值操作除了可以为 ...

  4. 苹果新的编程语言 Swift 语言进阶(十五)--协议

    协议定义了适合某个特定任务或功能需要的方法.属性和其它需求的一个蓝图.协议本身不提供这些需求的实现,它只是描述了一个任务或功能实现的蓝图. 协议与java 语言中的接口定义类似,都是描述了一个实现可以 ...

  5. 苹果新的编程语言 Swift 语言进阶(十四)--扩展

    扩展是为一个已经存在的类.结构.枚举类型添加新功能的一种方式,包括为不能存取源代码的那些已经存在的类型添加功能. 扩展类似于Objective-C语言中的类别,与类别不同的是Swift语言的扩展没有名 ...

  6. 苹果新的编程语言 Swift 语言进阶(九)--方法和下标

    一.方法 方法是与特定类型相关的函数.与属性一样,方法也包括实例方法和类型方法. 类.结构.枚举都能定义实例方法,用来封装或实现给定类型的一个实例相关的功能或特定任务. 类.结构.枚举也能定义与类型本 ...

  7. 苹果新的编程语言 Swift 语言进阶(七)--枚举、结构、类

    Swift语言中,具有类特征的类型包括三种,即枚举类型.结构类型(包括基本类型,基本类型实际都是结构类型的特例).类.其中枚举类型.结构类型是属于值类型,类属于引用类型.三种类型都可以添加属性.方法. ...

  8. 苹果新的编程语言 Swift 语言进阶(二)--基本数据类型

    一  .   常量和变量 Swift语言 对常量和变量的声明进行了明确的区分 Swift语言的常量类型比C 语言的constants类型更加强大,语义更加明确. 常量和变量的区别是常量在设置或初始化后 ...

  9. 苹果新的编程语言 Swift 语言进阶(五)--控制流

    Swift 语言支持C语言全部的控制语句.包含for  和while循环语句,if和switch条件语句,以及break和continue控制语句等. Swift 语言除了支持以上语句,还添加了一个f ...

  10. 苹果新的编程语言 Swift 语言进阶(十六)--泛型

    泛型允许你定义一个宽松.可重用的函数或者类型,使用泛型能够避免代码的重复,也能以更清楚和抽象的方式来表达程序的意图. 泛型是Swift语言提供的强大功能之一,Swift提供的许多标准库都使用了泛型来创 ...

随机推荐

  1. Redis 学习笔记1:CentOS 6.7下安装Redis

    在linux环境搭建Redis环境,首先从官网(http://redis.io/)下载Redis 版本,本人使用的3.21版本. 1. 将redis 解压到  /usr/local目录下. [root ...

  2. 关于bootstrap在IE8下不能支持自适应的问题

    说到这个问题,我就想吐槽下IE了,开发这么多版本,每个版本都有一些这样那样的问题不支持,别的正常的浏览器咋都能支持呢?真是垃圾浏览器!!!! 说归说,但是IE现在用的人多啊,怎么办?这个问题还是得解决 ...

  3. EBS技术开发之返利开发

    返利是指公司间应收款项按一定比率的返还给客户.返利开发实质就是实现对应收发票的更改和新增(暂时我的理解) 一.对发票行更改 PACKAGE AP_INVOICE_LINES_ALL_PRIVATE I ...

  4. tomcat启动批处理——startup.bat

    从文件命名上看就知道这是一个启动批处理,这个批处理的主要功能就是为了找到另一个批处理catalina.bat,并且执行catalina.bat. 一开始就用if "%OS%" == ...

  5. Dynamics CRM2013/2015 检索实体属性的两种方式

    昨天有朋友问起如何查询一个字段属性是否存在于某个实体中,一般这个问题我们会采取最直观的查询方式即MetadataBrowser,该工具是一个zip解决方案包在SDK中的如下目录内"\SDK\ ...

  6. Spark内存管理-UnifiedMemoryManager和StaticMemoryManager

    在Spark-1.6.0中,引入了一个新的参数spark.memory.userLegacyMode(默认值为false),表示不使用Spark-1.6.0之前的内存管理机制,而是使用1.6.0中引入 ...

  7. Linux内核线程

    内核线程是直接由内核本身启动的进程.内核线程实际上是将内核函数委托给独立的进程,与系统中其他进程"并行"执行(实际上,也并行于内核自身的执行),内核线程经常被称为内核"守 ...

  8. 1、Android测试入门

    编写和运行测试时Android APP开发周期中的重要的一环.好的测试可以让你非常容易的在开发过程中发现bug,提升你对自己代码的自信.使用Android Studio,你可以在物理设备或者虚拟机中运 ...

  9. HMM:隐马尔科夫模型-前向算法

    http://blog.csdn.net/pipisorry/article/details/50722376 目标-解决HMM的基本问题之一:已知HMM模型λ及观察序列O,如何计算P(O|λ)(计算 ...

  10. iOS中分段控制器与UIScrollView结合使用

    指定根视图: // 设置window的根视图控制器 self.window.rootViewController = [[UINavigationController alloc] initWithR ...