发布于 2015-06-14 01:59:50 | 198 次阅读 | 评论: 0 | 来源: 网络整理

值类型的构造器代理

构造器可以通过调用其它构造器来完成实例的部分构造过程。这一过程称为构造器代理,它能减少多个构造器间的代码重复。

构造器代理的实现规则和形式在值类型和类类型中有所不同。值类型(结构体和枚举类型)不支持继承,所以构造器代理的过程相对简单,因为它们只能代理任务给本身提供的其它构造器。类则不同,它可以继承自其它类(请参考继承),这意味着类有责任保证其所有继承的存储型属性在构造时也能正确的初始化。这些责任将在后续章节类的继承和构造过程中介绍。

对于值类型,你可以使用self.init在自定义的构造器中引用其它的属于相同值类型的构造器。并且你只能在构造器内部调用self.init

注意,如果你为某个值类型定义了一个定制的构造器,你将无法访问到默认构造器(如果是结构体,则无法访问逐一对象构造器)。这个限制可以防止你在为值类型定义了一个更复杂的,完成了重要准备构造器之后,别人还是错误的使用了那个自动生成的构造器。


注意:
假如你想通过默认构造器、逐一对象构造器以及你自己定制的构造器为值类型创建实例,我们建议你将自己定制的构造器写到扩展(extension)中,而不是跟值类型定义混在一起。想查看更多内容,请查看扩展章节。
 

下面例子将定义一个结构体Rect,用来展现几何矩形。这个例子需要两个辅助的结构体SizePoint,它们各自为其所有的属性提供了初始值0.0


struct Size {
    var width = 0.0, height = 0.0
}
struct Point {
    var x = 0.0, y = 0.0
}

你可以通过以下三种方式为Rect创建实例--使用默认的0值来初始化originsize属性;使用特定的originsize实例来初始化;使用特定的centersize来初始化。在下面Rect结构体定义中,我们为着三种方式提供了三个自定义的构造器:


struct Rect {
    var origin = Point()
    var size = Size()
    init() {}
    init(origin: Point, size: Size) {
        self.origin = origin
        self.size = size
    }
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}

第一个Rect构造器init(),在功能上跟没有自定义构造器时自动获得的默认构造器是一样的。这个构造器是一个空函数,使用一对大括号{}来描述,它没有执行任何定制的构造过程。调用这个构造器将返回一个Rect实例,它的originsize属性都使用定义时的默认值Point(x: 0.0, y: 0.0)Size(width: 0.0, height: 0.0)


let basicRect = Rect()
// basicRect 的原点是 (0.0, 0.0),尺寸是 (0.0, 0.0)

第二个Rect构造器init(origin:size:),在功能上跟结构体在没有自定义构造器时获得的逐一成员构造器是一样的。这个构造器只是简单的将originsize的参数值赋给对应的存储型属性:


let originRect = Rect(origin: Point(x: 2.0, y: 2.0),
    size: Size(width: 5.0, height: 5.0))
// originRect 的原点是 (2.0, 2.0),尺寸是 (5.0, 5.0)

第三个Rect构造器init(center:size:)稍微复杂一点。它先通过centersize的值计算出origin的坐标。然后再调用(或代理给)init(origin:size:)构造器来将新的originsize值赋值到对应的属性中:

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),


size: Size(width: 3.0, height: 3.0))

// centerRect 的原点是 (2.5, 2.5),尺寸是 (3.0, 3.0)

构造器init(center:size:)可以自己将originsize的新值赋值到对应的属性中。然而尽量利用现有的构造器和它所提供的功能来实现init(center:size:)的功能,是更方便、更清晰和更直观的方法。


注意:
如果你想用另外一种不需要自己定义init()init(origin:size:)的方式来实现这个例子,请参考扩展
 

最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务