[swift-users] Refining generics in classes

Fred Appelman swift-users at appelman.net
Thu Nov 16 02:31:32 CST 2017


If I change it slightly

protocol JSONDecodable { init() }
protocol CompressedDecodable: JSONDecodable { }

class NetworkRequest<T: JSONDecodable> {

    var response: T?

    func doAThing() {
      response = doSomething()
    }
    func doSomething<T: JSONDecodable>() -> T {
      print("One: \(T.self)")
      return T()
    }

}

class CompressedNetworkRequest<U: CompressedDecodable>: NetworkRequest<U> {

  override func doSomething<U: CompressedDecodable>() -> U {
    print("Two: \(U.self)")
    return U()
  }

}

struct Uno: JSONDecodable { }
struct Dos: CompressedDecodable { }

NetworkRequest<Uno>().doAThing()
CompressedNetworkRequest<Dos>().doAThing()
I do get the output:

One: Uno
Two: Dos
But I also get a crash error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT).

—
Fred




From: Jon Shier via swift-users <swift-users at swift.org>
Reply: Jon Shier <jon at jonshier.com>
Date: 16 November 2017 at 05:43:06
To: Седых Александр via swift-users <swift-users at swift.org>
Subject:  [swift-users] Refining generics in classes  

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 at swift.org
https://lists.swift.org/mailman/listinfo/swift-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20171116/68d96d00/attachment.html>


More information about the swift-users mailing list