Swift:如何在变量中保存泛型类型的任何可能实例
Swift: How to hold any possible instance of a generic type in a variable
我想做的事情的提炼是这样的:
public struct HolderOfWrappers
{
let anyWrappedItem: MyResource<Any>
}
public struct MyResource<A>
{
let wrappedItem : A
let convert: String -> A
}
func holdResource<A>( resource: MyResource<A> ) -> HolderOfWrappers
{
// Error on this line, A is not Any...
let wrapHolder : HolderOfWrappers = HolderOfWrappers( resource )
return wrapHolder
}
就目前而言,此代码在我尝试构建 HolderOfWrappers
:
的最后一个 holdResource
方法中产生编译器错误
Cannot convert the expression's type 'MyResource<A>' to type '(anyWrappedItem: MyResource<Any>)'
这是可以理解的,因为代码表明 HolderOfWrappers 只能保存为 Any 类型构建的 MyResource,而不是任何可能的类型。 HolderOfWrappers
我真正想要的是这样的:
public struct HolderOfWrappers
{
let anyWrappedItem: MyResource<>
}
甚至 MyResource<*>
- 我试图用这段代码说我想要一个可以保存任何类型的 MyResource 的变量。如果我尝试使用任何一种语法,我都会收到一个编译器错误,它需要一个类型。
我可以通过类型 Any
得到 anyWrappedItem
,但是你会丢失类型信息以备将来使用。我也不希望 HolderOfWrappers 是通用的(因为那样我以后就会遇到同样的问题)。
这几乎就像我试图将泛型类型视为 anyWrappedItem
存储变量的协议一样,由于其他原因它不会工作...
这个怎么样
protocol Wrapper {}
public struct HolderOfWrappers {
let anyWrappedItem: MyResource<Wrapper>
}
public struct MyResource<A> {
let wrappedItem : A
let convert: String -> A
}
func holdResource( resource: MyResource<Wrapper>) -> HolderOfWrappers {
// Error on this line, A is not Any...
let wrapHolder : HolderOfWrappers = HolderOfWrappers(anyWrappedItem: resource)
return wrapHolder
}
当然,缺点是您必须对传递给 MyResource 的任何类型 A 执行 extension A: Wrapper { }
。
我认为您可以通过在 HolderOfWrappers
init
方法中放置一个通用参数来做您想做的事。基本上,init
方法只是使用您提供的 resource
生成一个新的 MyResource
,如下所示:
public struct HolderOfWrappers {
let anyWrappedItem: MyResource<Any>
public init<A>(resource: MyResource<A>) {
self.anyWrappedItem = MyResource(wrappedItem: resource.wrappedItem, convert: resource.convert)
}
}
我想这会如你所愿。我不知道它是否会更慢,因为你正在初始化一个全新的 MyResource
而不是仅仅复制一个。
无论如何,它使得 HolderOfWrappers
本身不是通用的,并且会用 MyResource<Any>
填充 anyWrappedItem
,该 MyResource<Any>
与 resource
具有相同的值你传入的。
我想做的事情的提炼是这样的:
public struct HolderOfWrappers
{
let anyWrappedItem: MyResource<Any>
}
public struct MyResource<A>
{
let wrappedItem : A
let convert: String -> A
}
func holdResource<A>( resource: MyResource<A> ) -> HolderOfWrappers
{
// Error on this line, A is not Any...
let wrapHolder : HolderOfWrappers = HolderOfWrappers( resource )
return wrapHolder
}
就目前而言,此代码在我尝试构建 HolderOfWrappers
:
holdResource
方法中产生编译器错误
Cannot convert the expression's type 'MyResource<A>' to type '(anyWrappedItem: MyResource<Any>)'
这是可以理解的,因为代码表明 HolderOfWrappers 只能保存为 Any 类型构建的 MyResource,而不是任何可能的类型。 HolderOfWrappers
我真正想要的是这样的:
public struct HolderOfWrappers
{
let anyWrappedItem: MyResource<>
}
甚至 MyResource<*>
- 我试图用这段代码说我想要一个可以保存任何类型的 MyResource 的变量。如果我尝试使用任何一种语法,我都会收到一个编译器错误,它需要一个类型。
我可以通过类型 Any
得到 anyWrappedItem
,但是你会丢失类型信息以备将来使用。我也不希望 HolderOfWrappers 是通用的(因为那样我以后就会遇到同样的问题)。
这几乎就像我试图将泛型类型视为 anyWrappedItem
存储变量的协议一样,由于其他原因它不会工作...
这个怎么样
protocol Wrapper {}
public struct HolderOfWrappers {
let anyWrappedItem: MyResource<Wrapper>
}
public struct MyResource<A> {
let wrappedItem : A
let convert: String -> A
}
func holdResource( resource: MyResource<Wrapper>) -> HolderOfWrappers {
// Error on this line, A is not Any...
let wrapHolder : HolderOfWrappers = HolderOfWrappers(anyWrappedItem: resource)
return wrapHolder
}
当然,缺点是您必须对传递给 MyResource 的任何类型 A 执行 extension A: Wrapper { }
。
我认为您可以通过在 HolderOfWrappers
init
方法中放置一个通用参数来做您想做的事。基本上,init
方法只是使用您提供的 resource
生成一个新的 MyResource
,如下所示:
public struct HolderOfWrappers {
let anyWrappedItem: MyResource<Any>
public init<A>(resource: MyResource<A>) {
self.anyWrappedItem = MyResource(wrappedItem: resource.wrappedItem, convert: resource.convert)
}
}
我想这会如你所愿。我不知道它是否会更慢,因为你正在初始化一个全新的 MyResource
而不是仅仅复制一个。
无论如何,它使得 HolderOfWrappers
本身不是通用的,并且会用 MyResource<Any>
填充 anyWrappedItem
,该 MyResource<Any>
与 resource
具有相同的值你传入的。