Subclass instance passed to closure expecting parent class “cannot convert value of type to expected argument type”


(Eric Conner) #1

Hello all!

I hope it's not frowned upon to repost a question here from Stack Overflow,
but I have not found help there. In any case, the email gets some nice
formatting out of it :-D.

I am trying to create a subclass with a generic type that can be passed
into a completion block, but am getting the following error:

Cannot convert value of type '(ModelListResponse) -> ()' to expected
argument type '(APIResponse) -> ()'

Parent class:

import ObjectMapper
class APIResponse: Mappable {
    var status: String!
    var message: String?

    required init?(map: Map) {}

    func mapping(map: Map) {
        status <- map["status"]
        message <- map["message"]
    }}

Subclass:

import ObjectMapper
class ModelListResponse<T: Mappable>: APIResponse {
    var data: ModelList<T>?

    required init?(map: Map) {
        super.init(map: map)
    }

    override func mapping(map: Map) {
        super.mapping(map: map)
        data <- map["data"]
    }}

Then I have a function definition:

func _GET(path: String, parameters: Parameters, completion:@escaping
(APIResponse) -> ())

And I'm trying to call it like so:

// error is on this lineself._GET(path: "/rest/posts", parameters:
parameters) { (response: ModelListResponse<Post>) in
    // ...}

But here I get the error about how ModelListResponse cannot be converted.
Isn't a ModelListResponse an APIResponse? I don't understand why this does
not work.

I managed to get around the issue by using a generic. Though I'm not sure
why this works and the above code does not. Here is my working declaration:

func _GET<T: Mappable>(path: String, parameters: Parameters,
completion:@escaping (T) -> ()) { }

Thanks!


(Kenny Leung) #2

Could it be because ModelListResponse is Generalized while APIResponse is not?

-Kenny

···

On Sep 28, 2016, at 5:43 PM, Eric Conner via swift-users <swift-users@swift.org> wrote:

Hello all!

I hope it's not frowned upon to repost a question here from Stack Overflow, but I have not found help there. In any case, the email gets some nice formatting out of it :-D.

I am trying to create a subclass with a generic type that can be passed into a completion block, but am getting the following error:

Cannot convert value of type '(ModelListResponse) -> ()' to expected argument type '(APIResponse) -> ()'
Parent class:

import ObjectMapper

class APIResponse: Mappable {

var status: String!

var message: String?

    required init
?(map: Map) {}

    func mapping
(map: Map) {

        status
<- map["status"]

        message
<- map["message"]

}
}
Subclass:

import ObjectMapper

class ModelListResponse<T: Mappable>: APIResponse {

var data: ModelList<T>?

    required init
?(map: Map) {

super.init(map: map)

}

override func mapping(map: Map) {

super.mapping(map: map)

        data
<- map["data"]

}
}
Then I have a function definition:

func _GET(path: String, parameters: Parameters, completion:@escaping (APIResponse) -> ())
And I'm trying to call it like so:

// error is on this line
self._GET(path: "/rest/posts", parameters: parameters) { (response: ModelListResponse<Post>) in

// ...
}
But here I get the error about how ModelListResponse cannot be converted. Isn't a ModelListResponse an APIResponse? I don't understand why this does not work.

I managed to get around the issue by using a generic. Though I'm not sure why this works and the above code does not. Here is my working declaration:

func _GET<T: Mappable>(path: String, parameters: Parameters, completion:@escaping (T) -> ()) { }
Thanks!

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Mark Lacey) #3

Hello all!

I hope it's not frowned upon to repost a question here from Stack Overflow, but I have not found help there. In any case, the email gets some nice formatting out of it :-D.

I am trying to create a subclass with a generic type that can be passed into a completion block, but am getting the following error:

Cannot convert value of type '(ModelListResponse) -> ()' to expected argument type '(APIResponse) -> ()'
Parent class:

import ObjectMapper

class APIResponse: Mappable {
    var status: String!
    var message: String?

    required init?(map: Map) {}

    func mapping(map: Map) {
        status <- map["status"]
        message <- map["message"]
    }
}
Subclass:

import ObjectMapper

class ModelListResponse<T: Mappable>: APIResponse {
    var data: ModelList<T>?

    required init?(map: Map) {
        super.init(map: map)
    }

    override func mapping(map: Map) {
        super.mapping(map: map)
        data <- map["data"]
    }
}
Then I have a function definition:

func _GET(path: String, parameters: Parameters, completion:@escaping (APIResponse) -> ())
And I'm trying to call it like so:

// error is on this line
self._GET(path: "/rest/posts", parameters: parameters) { (response: ModelListResponse<Post>) in
    // ...
}
But here I get the error about how ModelListResponse cannot be converted. Isn't a ModelListResponse an APIResponse? I don't understand why this does not work.

Below is a simplified version of what you’re attempting to do, which will hopefully shed some light.

In your example, you’ve got a function, _GET() which expects to be passed a function that can take an APIReponse (which it could then invoke methods on). You’re instead passing in a function that can take a ModelListResponse<Post>, and that function would expect to be able to invoke methods on a ModelListResponse<Post>, but the caller (_GET()), might pass in an APIRespons that is not a ModelListResponse<Post>.

Mark

class A {}
class B : A {
  func gotcha() {}
}

func apply(_ f: (A) -> (), _ a: A) { f(a) }

func processB(_ b: B) -> () { b.gotcha() }

apply(processB, A()) // cannot convert value of type '(B) -> ()' to expected argument type '(A) -> ()'

···

On Sep 28, 2016, at 5:43 PM, Eric Conner via swift-users <swift-users@swift.org> wrote:

I managed to get around the issue by using a generic. Though I'm not sure why this works and the above code does not. Here is my working declaration:

func _GET<T: Mappable>(path: String, parameters: Parameters, completion:@escaping (T) -> ()) { }
Thanks!

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users