欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Swift优雅的copy一个类对象

程序员文章站 2022-05-26 14:15:36
...

Struct的Copy

我们都知道Swift中的结构体是值传递.也就是说如果我们将某个结构体对象A赋值给对象B.
如果我们将A里面的属性进行改变,实际上B对象的属性并没有跟着改变.
这个的本质其实是B对象是另外开辟了一段内存空间.已经完完全全和A分道扬镳了.

Class的Copy

类的Copy是引用传递,其实质是内存地址的传递.所以你可以得出与OC环境下一样的情况.
当然,我们也可以通过类继承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类型的对象

然后我们来进行测试.

func classCopyExample() {
        
        //  源
        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

这样我们就完成了对类对象的Copy行为了.
当然我们让Student类继承NSObject,再遵守Copyable协议也是可以的.