英文:
swift type erasure understanding, Cannot convert value of type 'AnyMapper<Payload, [Post]>' to expected element type 'AnyMapper<Payload, User>
问题
我尝试将两个对象放入数组,但是我收到了这个错误:**无法将类型为 'AnyMapper<Payload, [Post]>' 的值转换为预期的元素类型 'AnyMapper<Payload, User>'**。有人能解释一下如何修复吗?
英文:
struct Payload {}
struct User {}
struct Post {}
protocol Mapper {
associatedtype PayloadType
associatedtype ResultType
func map(_ payload: PayloadType) -> ResultType
}
class AnyMapper<P, R>: Mapper {
private var _mapClouser: (P) -> R
init<M: Mapper>(_ mapper: M) where M.PayloadType == P, M.ResultType == R {
_mapClouser = mapper.map(_:)
}
func map(_ payload: P) -> R {
_mapClouser(payload)
}
}
class UserMapper: Mapper {
func map(_ payload: Payload) -> User {
return User()
}
}
class PostsMapper: Mapper {
func map(_ payload: Payload) -> [Post] {
return [Post(), Post(), Post()]
}
}
let userMapper = AnyMapper(UserMapper())
let postsMapper = AnyMapper(PostsMapper())
var array: [AnyMapper] = [userMapper, postsMapper] <<< Error: Cannot convert value of type 'AnyMapper<Payload, [Post]>' to expected element type 'AnyMapper<Payload, User>'
I tried to put 2 objects into array, but I get this error: Cannot convert value of type 'AnyMapper<Payload, [Post]>' to expected element type 'AnyMapper<Payload, User>'
Can someone explain to me how to fix it?
答案1
得分: 0
[Post]
和 User
不是相同的类型。不需要一个擦除类型将它们放入同一个数组中。
var array: [任意映射器] = [UserMapper(), PostsMapper()]
英文:
[Post]
and User
are not the same type. You don't need an erasing type to put them into the same array.
var array: [any Mapper] = [UserMapper(), PostsMapper()]
答案2
得分: 0
AnyMapper
本身并不是一个类型。它是一个类型构造器。基本上,它是一个“函数”,它
- 在编译时运行,
- 以名为
P
和R
的参数形式接受类型,并且 - 返回一个类型。
所以,例如如果你写 AnyMapper<Payload, User>
,那是对类型构造器 AnyMapper
的一个编译时函数调用,传递了参数 Payload
和 User
。它返回一个类型,我们可以用相同的语法引用它,AnyMapper<Payload, User>
。
通常,Swift 可以推断参数类型,所以尽管你没有显式传递它们,Swift 会为你传递它们。
这就是这两行代码上发生的事情:
let userMapper = AnyMapper(UserMapper())
let postsMapper = AnyMapper(PostsMapper())
这两行代码中的每一行在推断了 P
和 R
参数后都“调用”了 AnyMapper
。我们可以使 P
和 R
参数显式,也可以使返回的类型显式,就像这样:
let userMapper: AnyMapper<Payload, User> = AnyMapper<Payload, User>(UserMapper())
let postsMapper: AnyMapper<Payload, [Post]> = AnyMapper<Payload, [Post]>(PostsMapper())
所以现在我们可以看到你正在创建两个不同类型的对象。
接着你写了这个:
var array: [AnyMapper] = [userMapper, postsMapper]
由于你没有显式地传递类型参数给 AnyMapper
,你要求 Swift 推断这些参数。它通过查看数组字面量的第一个元素 userMapper
来推断。基于此,它推断 P = Payload
和 R = User
,所以它的行为就像你写了这样:
var array: [AnyMapper<Payload, User>] = [userMapper, postsMapper]
但是 postsMapper
不是一个 AnyMapper<Payload, User>
,所以 Swift 不能编译该语句。
所有这些意味着 AnyMapper
只擦除了包装的 Mapper
的具体类型,但没有擦除它的 PayloadType
和 ResultType
关联类型。
不清楚你为什么想要将 userMapper
和 postsMapper
放在同一个数组中。它们有不同的结果类型,所以你不能通用地处理它们的结果。也许如果你解释一下为什么你认为你需要把它们都放在一个数组中,我们可以给你更好的指导。
英文:
AnyMapper
by itself is not a type. It is a type constructor. Essentially, it is a “function” that
- runs at compile time,
- takes types as arguments named
P
andR
, and - returns a type.
So for example if you say AnyMapper<Payload, User>
, that's a compile-time function call to the type constructor AnyMapper
, passing the arguments Payload
and User
. It returns a type, which we just refer to using the same syntax, AnyMapper<Payload, User>
.
Often, Swift can deduce the argument types, so although you don't pass them explicitly, Swift passes them for you.
That's what's happening on these two lines:
let userMapper = AnyMapper(UserMapper())
let postsMapper = AnyMapper(PostsMapper())
Each of those lines “calls“ AnyMapper
after deducing the P
and R
arguments. We can make the P
and R
arguments explicit, and also make the returned types explicit, like this:
let userMapper: AnyMapper<Payload, User> = AnyMapper<Payload, User>(UserMapper())
let postsMapper: AnyMapper<Payload, [Post]> = AnyMapper<Payload, [Post]>(PostsMapper())
So now we can see that you're creating two objects of two different types.
You next write this:
var array: [AnyMapper] = [userMapper, postsMapper]
Since you're not explicitly passing type arguments to AnyMapper
, you're asking Swift to deduce the arguments. It does so by looking at the first element of the array literal, userMapper
. Based on that, it deduces P = Payload
and R = User
, so it acts like you wrote this:
var array: [AnyMapper<Payload, User>] = [userMapper, postsMapper]
But postsMapper
is not an AnyMapper<Payload, User>
, so Swift can't compile that statement.
What all this means is that AnyMapper
erases only the wrapped Mapper
's specific type, but not its PayloadType
and ResultType
associated types.
It's not clear why you would want to put userMapper
and postsMapper
in the same array anyway. They have different result types, so you wouldn't be able to treat their results generically. Perhaps if you explain why you think you need to put them both in a single array, we can give you better guidance.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论