swift - 在 Swift 中更新不同数据类型属性的通用方法

标签 swift generics

我不知道是否可能,但我认为可以有办法做我想做的事。
我有以下情况:

enum ContactStatus: UInt {
    case requestSent = 0, requestReceived, requestProcessing, active, removed
}

struct Contact {
    var uid: String
    var name: String?
    var contactStatus: ContactStatus

    init(uid: String, name: String? = nil, contactStatus: ContactStatus = .requestSent) {
        self.uid = uid
        self.name = name
        self.contactStatus = contactStatus
    }
}

class ContactStorage: {
    private var contacts: [Contact]
    init(contacts: [Contact]) {
        contacts = contacts
    }

    func createContact(uid: String, contactStatus status: ContactStatus, name: String?) -> Contact {
        var newContact = Contact(uid: uid)
        newContact.contactStatus = status
        newContact.name = name
        newContacts.append(newContact)
        return newContact
    }
    func updateContact(status: ContactStatus, peerUId: String) {
        for (index, _) in contacts.enumerated() {
            if contacts[index].uid == peerUId {
                contacts[index].contactStatus = status
                return
            }
        }
    }
    func updateContact(name: String, peerUId: String) {
        for (index, _) in contacts.enumerated() {
            if contacts[index].uid == peerUId {
                contacts[index].name = name
                return
            }
        }
    }
}

正如我们所见,ContactStorage 有两个方法来更新联系人状态和姓名。
我希望使用通用数据类型或任何其他可能的方式将这两种方法合并为一种方法。

类似于:

func updateContact<T: Updateable>(peerUId: String, updatableProperty: T) {
    //implementation
}

是否可以只写一个方法而不是两个?

最佳答案

你可以“有点”用闭包来做到这一点。

“XXX”和“YYY”部分是您拥有的两种方法之间唯一不同的部分:

for (index, _) in contacts.enumerated() {
    if contacts[index].uid == peerUId {
        contacts[index].XXX = YYY
        return
    }
}

因此,如果我们想将其提取为一个方法,我们需要一个闭包作为参数来提供“XXX”部分。

闭包看起来像这样:

(inout Contact, T) -> Void

对于“YYY”部分,常规参数就可以了。

因此,该方法如下所示:

func updateProperty<T>(property: (inout Contact, T) -> Void, value: T, peerUId: String) {
    for (index, _) in contacts.enumerated() {
        if contacts[index].uid == peerUId {
            property(&contacts[index], value)
            return
        }
    }
}

你可以这样调用它:

updateProperty(property: {$0.name = $1}, value: "Tom", peerUId: "something")

另一种方法是完全删除“YYY”,并将其集成到闭包中:

func updateProperty(property: (inout Contact) -> Void, peerUId: String) {
    for (index, _) in contacts.enumerated() {
        if contacts[index].uid == peerUId {
            property(&contacts[index])
            return
        }
    }
}

用法:

updateProperty(property: {$0.name = "Tom"}, peerUId: "something")

关于swift - 在 Swift 中更新不同数据类型属性的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46159162/

相关文章:

swift - 在 beginSheetModalForWindow 中尝试

c# - 泛型方法如何知道不可访问的类型? (或 "How I Lost a Dollar")

具有泛型、比较器和排序错误的 Java 类层次结构

java - 用抽象类的子类的对象填充通用列表

iOS 13.0 UIMenu 和 UIContextMenuConfiguration 的 UIAction

swift - 帮助 for in 循环

c - 通用 HashMap,不需要的输出 (C)

python - 如何在 Django 列表中排序

swift - 为什么 swift 不使用没有类型约束的通用返回参数来推断适当的重载函数?

arrays - 如何从具有重复范围的数组中获取具有唯一范围的数组?