Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 843
deanWombourne Avatar asked Dec 03 '25 16:12

deanWombourne


1 Answers

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

like image 121
Joakim Danielson Avatar answered Dec 06 '25 07:12

Joakim Danielson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!