<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8">
</head>
<body>
<div style="font-family:sans-serif"><div style="white-space:normal">
<p dir="auto">Hi Jon,</p>
<p dir="auto">To clarify for those wondering, this is happening because the <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">doAThing()</code> method dispatches statically to <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">doSomething()</code> based on <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">NetworkRequests</code>’s <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">T</code>; since <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">doAThing()</code> isn’t overridden in <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">CompressedNetworkRequest</code>, the method is inherited directly, including that static dispatch.<br>
To pull this example out a bit:</p>
<pre style="background-color:#F7F7F7; border-radius:5px 5px 5px 5px; margin-left:15px; margin-right:15px; max-width:90vw; overflow-x:auto; padding:5px; color:black" bgcolor="#F7F7F7"><code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0" bgcolor="#F7F7F7"><span style="color: #008800; font-weight: bold">protocol</span> <span style="color: #BB0066; font-weight: bold">X</span> {}
<span style="color: #008800; font-weight: bold">protocol</span> <span style="color: #BB0066; font-weight: bold">Y</span> : X {}
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Foo</span><T : X> {
<span style="color: #008800; font-weight: bold">var</span> <span style="color: #996633">value</span>: T
<span style="color: #008800; font-weight: bold">init</span>(value: T) {
<span style="color: #008800; font-weight: bold">self</span>.value = value
}
<span style="color: #008800; font-weight: bold">func</span> <span style="color: #0066BB; font-weight: bold">doSomething</span>() {
doThing(value)
}
}
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Bar</span><T : Y> : Foo<T> {}
<span style="color: #008800; font-weight: bold">func</span> <span style="color: #0066BB; font-weight: bold">doThing</span><T : X>(<span style="color: #008800; font-weight: bold">_</span> v: T) { <span style="color: #007020">print</span>(<span style="background-color: #fff0f0">"doThing<T : X>()"</span>) }
<span style="color: #008800; font-weight: bold">func</span> <span style="color: #0066BB; font-weight: bold">doThing</span><T : Y>(<span style="color: #008800; font-weight: bold">_</span> v: T) { <span style="color: #007020">print</span>(<span style="background-color: #fff0f0">"doThing<T : Y>()"</span>) }
<span style="color: #008800; font-weight: bold">extension</span> <span style="color: #BB0066; font-weight: bold">Int</span> : Y {}
Foo(value: <span style="color: #0000DD; font-weight: bold">42</span>).doSomething() <span style="color: #888888">// doThing<T : X></span>
Bar(value: <span style="color: #0000DD; font-weight: bold">42</span>).doSomething() <span style="color: #888888">// doThing<T : X></span>
</code></pre>
<p dir="auto">In order to not inherit that static dispatch, <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">doSomething</code> needs to be overridden in <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7">Bar</code>, even if to call the same function:</p>
<pre style="background-color:#F7F7F7; border-radius:5px 5px 5px 5px; margin-left:15px; margin-right:15px; max-width:90vw; overflow-x:auto; padding:5px; color:black" bgcolor="#F7F7F7"><code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0" bgcolor="#F7F7F7"><span style="color: #888888">// …</span>
<span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">Bar</span><T : Y> : Foo<T> {
<span style="color: #008800; font-weight: bold">override</span> <span style="color: #008800; font-weight: bold">func</span> <span style="color: #0066BB; font-weight: bold">doSomething</span>() {
doThing(value) <span style="color: #888888">// statically dispatches based on T : Y</span>
}
}
<span style="color: #888888">// …</span>
Foo(value: <span style="color: #0000DD; font-weight: bold">42</span>).doSomething() <span style="color: #888888">// doThing<T : X>()</span>
Bar(value: <span style="color: #0000DD; font-weight: bold">42</span>).doSomething() <span style="color: #888888">// doThing<T : Y>()</span>
</code></pre>
<p dir="auto">Unfortunately, I don’t think there’s a great way around this, short of duplicating the calls which do that sort of dispatch.<br>
If you can somehow funnel some of these calls through one call site, it might make your life a bit easier.</p>
<p dir="auto">— Itai</p>
<p dir="auto">On 15 Nov 2017, at 20:42, Jon Shier via swift-users wrote:</p>
</div>
<div style="white-space:normal"><blockquote style="border-left:2px solid #777; color:#777; margin:0 0 5px; padding-left:5px"><p dir="auto">        Swift Users:<br>
        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:<br>
<br>
protocol JSONDecodable { init() }<br>
protocol CompressedDecodable: JSONDecodable { }<br>
<br>
class NetworkRequest<T: JSONDecodable> {<br>
<br>
var response: T?<br>
<br>
func doAThing() {<br>
response = doSomething()<br>
}<br>
}<br>
<br>
class CompressedNetworkRequest<U: CompressedDecodable>: NetworkRequest<U> {<br>
<br>
}<br>
<br>
func doSomething<T: JSONDecodable>() -> T {<br>
print("One: \(T.self)")<br>
return T()<br>
}<br>
<br>
func doSomething<T: CompressedDecodable>() -> T {<br>
print("Two: \(T.self)")<br>
return T()<br>
}<br>
<br>
struct Uno: JSONDecodable { }<br>
struct Dos: CompressedDecodable { }<br>
<br>
NetworkRequest<Uno>().doAThing()<br>
CompressedNetworkRequest<Dos>().doAThing()<br>
<br>
In a playground this prints:<br>
<br>
One: Uno<br>
One: Dos<br>
<br>
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?<br>
<br>
<br>
<br>
Jon Shier<br>
_______________________________________________<br>
swift-users mailing list<br>
swift-users@swift.org<br>
<a href="https://lists.swift.org/mailman/listinfo/swift-users" style="color:#777">https://lists.swift.org/mailman/listinfo/swift-users</a></p>
</blockquote></div>
<div style="white-space:normal">
</div>
</div>
</body>
</html>