Home > other >  How can I conform 2 different protocols not in the same time necessarily but at least one of them in
How can I conform 2 different protocols not in the same time necessarily but at least one of them in

Time:01-03

I have a testFunction that try to get values for making an array of them. Since some types conform to CustomStringConvertible and some conform to CustomDebugStringConvertible I made 2 function with same name for each type. But I see Xcode complain about ambiguous issue, then I used deferent names which I would wish to keep the name like testFunction and not having testFunction1 and testFunction2.

Here is my codes:

func testFunction1<T: CustomStringConvertible>(_ values: T...) {
    
    var array: [String] = [String]()

    values.forEach { value in

        array.append(value.description)
    }

    // other code to use array later ...

}

func testFunction2<T: CustomDebugStringConvertible>(_ values: T...) {
    
    var array: [String] = [String]()

    values.forEach { value in

        array.append(value.debugDescription)
    }

    // other code to use array later ...
 
}

The issue is here: It can be possible that I must receive mixed values with deferent types! Swift print function could handle it, but my 2 function cannot they can accept just type that conform to CustomStringConvertible or CustomDebugStringConvertible! I am trying to solve the mixed type issue, in this way that my testFunction could be able to accept mixed value like print does.

Very important! I am looking to solve the issue with the approach I am working. I am not looking for some kind of super protocol that covers CustomStringConvertible and CustomDebugStringConvertible.

use case:

print("Hello, world!", 1, CGFloat.pi, CGSize.zero)

testFunction1("Hello, world!", 1, CGFloat.pi, CGSize.zero)

testFunction2("Hello, world!", 1, CGFloat.pi, CGSize.zero)

CodePudding user response:

Here is one way that doesn't use generics

func testFunction1(_ values: Any...) {
    var array: [String] = [String]()

    values.forEach { value in
        switch value.self {
        case is CustomStringConvertible:
            array.append((value as! CustomStringConvertible).description)
        case is CustomDebugStringConvertible:
            array.append((value as! CustomDebugStringConvertible).debugDescription)
        default:
            break
        }
    }
    // other code to use array later ...

}

CodePudding user response:

The problem here is your array. Set your array to var array: [T] = []

Edit: try removing the generic constraints.

func testFunction1(_ values: CustomStringConvertible...) {
    
}

func testFunction2(_ values: CustomDebugStringConvertible...) {
    
}

CodePudding user response:

I think Joakim Danielson is on the right path, but I would recommend this implementation to remove the duplication and the subtle filtering:

func testFunction(_ values: Any...) {
    let array: [String] = values.map {
        switch $0 {
        case let v as CustomStringConvertible: return v.description
        case let v as CustomDebugStringConvertible: return v.debugDescription
        default: return "\($0)"
        }
    }

    // other code to use array later ...

}
  • Related