Hi Jon,
To clarify for those wondering, this is happening because the
`doAThing()` method dispatches statically to `doSomething()` based on
`NetworkRequests`’s `T`; since `doAThing()` isn’t overridden in
`CompressedNetworkRequest`, the method is inherited directly, including
that static dispatch.
To pull this example out a bit:
```swift
protocol X {}
protocol Y : X {}
class Foo<T : X> {
var value: T
init(value: T) {
self.value = value
}
func doSomething() {
doThing(value)
}
}
class Bar<T : Y> : Foo<T> {}
func doThing<T : X>(_ v: T) { print("doThing<T : X>()") }
func doThing<T : Y>(_ v: T) { print("doThing<T : Y>()") }
extension Int : Y {}
Foo(value: 42).doSomething() // doThing<T : X>
Bar(value: 42).doSomething() // doThing<T : X>
```
In order to not inherit that static dispatch, `doSomething` needs to be
overridden in `Bar`, even if to call the same function:
```swift
// …
class Bar<T : Y> : Foo<T> {
override func doSomething() {
doThing(value) // statically dispatches based on T : Y
}
}
// …
Foo(value: 42).doSomething() // doThing<T : X>()
Bar(value: 42).doSomething() // doThing<T : Y>()
```
Unfortunately, I don’t think there’s a great way around this, short
of duplicating the calls which do that sort of dispatch.
If you can somehow funnel some of these calls through one call site, it
might make your life a bit easier.
— Itai
On 15 Nov 2017, at 20:42, Jon Shier via swift-users wrote:
Swift Users:
I have a generics use case which has somewhat stumped me. I have two
related protocols, JSONDecodable and CompressedDecodable, and
CompressedDecodable inherits from JSONDecodable (though that
relationship isn’t strictly necessary). I also have a generic
function that’s overloaded for each of those protocols. I’m trying
to write a class to make a network request expecting a generic
response type of either JSONDecodable or CompressedDecodable. However,
it doesn’t seem possible to write it in such a way that the overload
I need is called. Instead, it’s always the superclass’ type’s
overload that is called. For example:
protocol JSONDecodable { init() }
protocol CompressedDecodable: JSONDecodable { }
class NetworkRequest<T: JSONDecodable> {
var response: T?
func doAThing() {
response = doSomething()
}
}
class CompressedNetworkRequest<U: CompressedDecodable>:
NetworkRequest<U> {
}
func doSomething<T: JSONDecodable>() -> T {
print("One: \(T.self)")
return T()
}
func doSomething<T: CompressedDecodable>() -> T {
print("Two: \(T.self)")
return T()
}
struct Uno: JSONDecodable { }
struct Dos: CompressedDecodable { }
NetworkRequest<Uno>().doAThing()
CompressedNetworkRequest<Dos>().doAThing()
In a playground this prints:
One: Uno
One: Dos
Ultimately, I understand why this happens (NetworkRequest’s generic
type is always going to be JSONDecodable, no matter if it’s actually
a subtype). Is there any way, aside from completely duplicating the
class, to call the overload appropriate for the type passed in a class
like this?
Jon Shier
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users