I don't if its possible or not, but I think there can be a way to do what I want.
I have following situation:
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
}
}
}
}
As we can see, ContactStorage
has two methods to update contact status and name.
I am looking to merge these two methods in one using generic data types or any other possible way.
Something like:
func updateContact<T: Updateable>(peerUId: String, updatableProperty: T) {
//implementation
}
Is it possible to write only one method instead of two?
You can "kind of" do this with closures.
The "XXX" and "YYY" part is the only part that is different between the two methods you have:
for (index, _) in contacts.enumerated() {
if contacts[index].uid == peerUId {
contacts[index].XXX = YYY
return
}
}
So, if we want to extract this as a method, we need a closure as parameter to provide the "XXX" part.
That closure can look like this:
(inout Contact, T) -> Void
For the "YYY" part, a regular parameter will do just fine.
So, the method looks like this:
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
}
}
}
You would call it like this:
updateProperty(property: {$0.name = $1}, value: "Tom", peerUId: "something")
Another way to do this is to remove "YYY" completely, and integrate it into the closure:
func updateProperty(property: (inout Contact) -> Void, peerUId: String) {
for (index, _) in contacts.enumerated() {
if contacts[index].uid == peerUId {
property(&contacts[index])
return
}
}
}
Usage:
updateProperty(property: {$0.name = "Tom"}, peerUId: "something")