Swift (二) swift 中的原型模式

代码链接

继承自 NSObject 类

可以看到直接调用 copy 方法是可以的,但是程序会报错,这是以为 copy 是 NSObject 的方法,但是 NSObject 类并没有实现 NSCopying 协议,所以:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person: NSObject, NSCopying {

var name: String?
func copy(with zone: NSZone? = nil) -> Any {
let newP = Person()
newP.name = name
return newP
}
}

let p = Person()
let p2 = p.copy() as! Person
if let name = p2.name {
print(name)
}

非继承自 NSObject

而向 Dog 却并没有继承自 NSObject,所以程序运行的时候回报出没有 copy 成员的错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

class Dog: NSCopying {
var name: String?
var ower: Person?

func copy(with zone: NSZone? = nil) -> Any {
let copyDog = Dog()
copyDog.name = name
copyDog.ower = ower
return copyDog
}
}

let dog = Dog()
dog.name = "Tom"
let newDog = dog.copy() as! Dog
dog.name

继承类实现原型模式

这里出现了一个问题,就是 TianYuanDog 类型转换不成功,这是因为在 Dog 的 copy(with zone:) 方法中,我们是生成的 Dog 类,所以这里需要做一下修改

修改前:

1
2
3
4
5
6
func copy(with zone: NSZone? = nil) -> Any {
let copyDog = Dog()
copyDog.name = name
copyDog.ower = ower
return copyDog
}

let copyDog = Dog() 这里不能直接生成 Dog 对象,否则子类继承的话会出现问题

1
2
3
4
5
6
7
8
9
10
11
12
    func copy(with zone: NSZone? = nil) -> Any {
// let copyDog = Dog()
let dynamicType = type(of: self)
let copyDog = dynamicType.init()
copyDog.name = name
copyDog.ower = ower
return copyDog
}

required init() {

}

同样的,上面 Person 也要做修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person: NSObject, NSCopying {

var name: String?
func copy(with zone: NSZone? = nil) -> Any {
// let newP = Person()
let personType = type(of: self)
let newP = personType.init()

newP.name = name
return newP
}

required override init() {
}
}

继承类实现原型模式, 并添加新的属性

接下来 TianYuanDog 类 需要添加一个 ID 号,这个 ID 号在实例执行 copy 的时候也需要跟随一起 copy 的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class TianYuanDog: Dog {

var idNumber: Int?

required init() {}

init(number idNumber: Int) {
self.idNumber = idNumber
}

override func copy(with zone: NSZone?) -> Any {
let newCopy = super.copy(with: zone) as! TianYuanDog
newCopy.idNumber = self.idNumber
return newCopy
}
}

let tianyuan = TianYuanDog(number:123)
tianyuan.name = "中华田园犬"
let newCopy = tianyuan.copy(with: nil) as! TianYuanDog
newCopy.name
newCopy.idNumber

具体操作:

  1. 重写 copy(with:) 方法
  2. 如果需要添加 init() 方法,需要重写 require 的 init 方法
-------------本文结束谢谢欣赏-------------
Alice wechat