deanWombourne
deanWombourne

Reputation: 38475

Generic override in swift extension not being called

I have a generic type

enum ResultState<T> {
    case found(T)
}

with a few extensions

extension ResultState {

    func hello() { print("Hello") }
}

extension ResultState where T: Collection {

    func hello() { print("Hello, collection") }
}

These work perfectly and exactly as I would expect them to:

ResultState.found(1).hello() // prints "Hello"
ResultState.found([1]).hello() // prints "Hello, collection"

However, if they are called from within another generic function it doesn't behave the same

func myFunction<T>(_ state: ResultState<T>) {
    state.hello()
}

For example,

myFunction(ResultState.found(1)) // prints "Hello"
myFunction(ResultState.found([1]) // prints "Hello"

Now, the basic version of hello is called each time, even though inspecting T inside myFunction shows it is definitely Array<Int>.

Is this expected Swift behaviour?

If so, how would I work around it - how can I get the correct version of hello called from within myFunction?

Upvotes: 4

Views: 249

Answers (1)

Joakim Danielson
Joakim Danielson

Reputation: 52013

It looks to me that the information is lost for myFunction and only applies one level down so to speak for ResultState. Not sure this is the solution you want but one way is to define different functions in the same way you have different extensions.

func myFunction<T: Collection>(_ state: ResultState<T>)  {
    state.hello()
}

func myFunction<T>(_ state: ResultState<T>)  {
    state.hello()
}

Executing

ResultState.found(1).hello() 
ResultState.found([1]).hello() 

myFunction(ResultState.found(1))
myFunction(ResultState.found([1]))

will yield

Hello
Hello, collection
Hello
Hello, collection

Upvotes: 1

Related Questions