Godfather Godfather - 1 month ago 9
Swift Question

How to determine the generic type from protocol implementation

I have a protocol that has a function that can return a

String
or a
[String: String]
. This is my declaration:

protocol Test {
associatedtype T: Hashable
func returnSomething() -> T
}


Then I want a default implementation for
returnSomething
, so I made a protocol extension:

extension Test {
func returnSomething() -> T {
let valueToReturn = readValueFromPLISTthatCanReturnAStringOrDictionary() as T
return valueToReturn
}
}


So finally I have 2 clases,
TestString
and
TestDictionary
that both implements
Test
protocol and I want to indicate the
T
parameter and I want to use the default implementation. How I do this?

class TestString: Test {}

class TestDictionary: Test { }

class TestString: Test where Test.T = String or similar?

Answer

I have a protocol that has a function that can return a String or a [String: String]. This is my declaration:

No problem. Let's write that down.

enum StringOrDictionary {
    case string(String)
    case dictionary([String: String])
}

protocol Test {
    func returnSomething() -> StringOrDictionary
}

Then I want a default implementation for returnSomething, so I made a protocol extension:

Sounds good. I'll assume that readValueFromPLISTthatCanReturnAStringOrDictionary() actually returns Any, since that's what is returned by propertyList(from:).

extension Test {
    func returnSomething() -> StringOrDictionary {
        let value = readValueFromPLISTthatCanReturnAStringOrDictionary()

        switch value {
        case let string as String: return .string(string)
        case let dictionary as [String: String]: return .dictionary(dictionary)
        default: fatalError() // Or perhaps you'd like to do something else
        }
    }
}

It'd probably be nice to name your type something more meaningful than StringOrDictionary, but other than that, it should be pretty straightforward. Just make a type that means what you say. You want a type that means "OR" and that is an enum. (If you want a type that means "AND" that's a struct BTW.)