Home > Net >  swift : merge the same processing code by prop type, not by prop name?
swift : merge the same processing code by prop type, not by prop name?

Time:01-21

How to merge the same processing code by property type, not by property name?

Here is the case:

struct GroupA{
    let name: String
    let memberNum: Int
    
    var info: String{
        var result = "\(memberNum) "
        if memberNum > 1{
            result  = "members"
        }
        else{
            result  = "member"
        }
        return result   " in \(name)"
    }
}
  • code to merge

struct GroupB{
    let title: String
    let peopleCount: Int
    
    var info: String{
        var result = "\(peopleCount) "
        if peopleCount > 1{
            result  = "members "
        }
        else{
            result  = "member "
        }
        return result   "in \(title)"
    }
    
}

code usage example:

let a = GroupA(name: "haha ", memberNum: 5)

print(a.info)


let b = GroupB(title: "Bull", peopleCount: 6)

print(b.info)

Here is my solution:

struct GroupB{
    let title: String
    let peopleCount: Int
    
    var converted: GroupA{
        GroupA(name: title, memberNum: peopleCount)
    }
}
  • and usage:
let b = GroupB(title: "Bull", peopleCount: 6)

print(b.converted.info)

I think it is a little hard to use pop

reflection is an option


for the following example:

I think it is a little tough to use reflection

struct GroupC{
    let title: String
    let peopleCount: Int
    let leaderName: String
}

Any other better idea?


PS:

  • to merge

var info: String{ ... }

  • "processing code" is

" sth ( number) sth (title) sth"

number in groupA is memberNum, number in groupB is peopleCount

title is much alike

just a simple demo pattern

CodePudding user response:

If I understood correctly, you don't want to merge, you want to factorize...

So:

struct InfoFormatting {
    static func infos(from text: String, andNumber number: Int) -> String {
        var result = "\(number) "
        if number > 1 {
            result  = "number"
        }
        else {
            result  = "number"
        }
        return result   " in \(text)"
    }
}

I've created InfoFormatting, but it could be elsewhere, it depends on your architecture on where it would make more sense.

Then:

struct GroupA {
   ...
    var info: String { 
        InfoFormatting.infos(from: name, andNumber: memberNum)
    }
}

struct GroupA {
   ...
    var info: String { 
        InfoFormatting.infos(from: title, andNumber: peopleCount)
    }
}

That is the basic factorization.

Now, you could also use instead a protocol:

protocol InfoFormatter {
    var infos: String { get }
}

extension InfoFormatter {
   func infos(from text: String, andNumber number: Int) -> String {
        var result = "\(number) "
        if number > 1 {
            result  = "number"
        }
        else {
            result  = "number"
        }
        return result   " in \(text)"
    }
}

And make GroupA & GroupB compliant with it:

struct GroupA: InfoFormatter {
    let name: String
    let memberNum: Int
    
    var info: String {
        infos(from: name, andNumber: memberNum)
    }
}

struct GroupB: InfoFormatter {
    let title: String
    let peopleCount: Int
    
    var info: String {
        infos(from: title, andNumber: peopleCount)
    }
}
  •  Tags:  
  • Related