「本文已参与周末学习计划,点击查看详情 」
这是我参与更文挑战的第5天,活动详情查看: 更文挑战
struct的Copy
Swift中struct是值传递。也就是说如果我们将某个结构体对象A赋值给对象B。
如果我们将A里面的属性进行改变,实际上B对象的属性并没有跟着改变。
这个的本质其实是B对象是另外开辟了一段内存空间,已经完完全全和A分道扬镳了。
更本质的就是Swift其写时复制技术。
我们举个例子:
/// 源
var array1 = [0, 1, 2, 3]
/// 值传递
var array2 = array1
/// 变化前
print("before:\(array1)")
print("before:\(array2)")
/// 改变源
array1.append(4)
/// 源改变了
print("after:\(array1)")
/// 我还是我
print("after:\(array2)")
复制代码打印结果中可以很好的体现:
before array1:[0, 1, 2, 3]
before array2:[0, 1, 2, 3]
after array1:[0, 1, 2, 3, 4]
after array2:[0, 1, 2, 3]
复制代码class的Copy
Swift中class的copy是引用传递,其实质是内存地址的传递。所以你可以得出与OC环境下一样的情况。
很多从OC转过来写Swift的朋友,经常会有一种习惯,那就是但凡使用class,必然会想要继承NSObject。
在OC中,所以的类都需要继承NSObject,但是在Swift中,class继承NSObject不是必须的,可以说,减少继承NSObject,可以减少很多历史包袱,所以在尝试写一个工具类的时候,可以更简单一点。
当然继承了class继承了NSObject,那么你就完全可以通过遵守NSCopying那一套规则进行复制了。这不是本文想要说的核心点。
既然我们都使用Swift了,那么就不能用更优雅的Copy吗?
有大佬说过–”面向接口编程“的原则告诉我们,我们应该让某个类能够进行Copy, 是要实现某个接口,而不是继承自某个子类!
所以我们先来写一个协议
protocol Copyable {
    
    associatedtype T
    
    func copyable() -> T
}
复制代码然后我们让我们创建的Student类遵守该协议
class Student: Copyable {
    
    var name: String
    
    /// 关联类型进行指定
    typealias T = Student
    
    
    /// 初始化方法
    ///
    /// - Parameter name: name
    init(name: String) {
        self.name = name
    }
    
    /// 实现Copy协议
    ///
    /// - Returns: 拷贝的对象
    func copyable() -> Student {
        return Student(name: self.name)
    }
}
复制代码需要说明的是协议中的associatedtype关联类型。
定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分将会非常有用。
关联类型为协议中的某个类型提供了一个占位名(或者说别名),其代表的实际类型在协议被采纳时才会被指定。
你可以理解为在协议中声明了某个类型T, 协议的copyable()方法返回一个T类型的对象,而在Student类遵守协议的时候,T被指明为Student类型,进而实现copyable()方法返回一个Student类型的对象。
值得注意的是,在上面的例子中即使你没有写typealias T = Student这段代码,Swift的自动推断功能也会自动将T与Student自动关联起来。
然后我们来进行测试.
///  源
let student = Student(name: "season")
///  拷贝
let student2 = student.copyable()
///  引用传递
let student3 = student
/// 打印改变前的数据
print("before student.name: \(student.name)")
print("before student2.name: \(student2.name)")
print("before student3.name: \(student3.name)")
/// 变化
student.name = "soso"
/// 打印改变后的数据
print("after student.name: \(student.name)")
print("after student2.name: \(student2.name)")
print("after student3.name: \(student3.name)")
复制代码打印的日志为
before student.name: season
before student2.name: season
before student3.name: season
after student.name: soso
after student2.name: season
after student3.name: soso
复制代码这样我们就完成了对class对象的Copy行为了。
可见面向协议编程,在化繁为简这方面,真的是做的很好。






















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)
