2015-02-09 50 views
4

的什么,我试图做的是这样的蒸馏:斯威夫特:如何保持一个泛型类型的任何可能的情况下在一个变量

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 
} 

既然这样,这个代码产生编译器错误在最后holdResource方法,其中我试图建立一个HolderOfWrappers

Cannot convert the expression's type 'MyResource<A>' to type '(anyWrappedItem: MyResource<Any>)' 

这是可以理解的代码表示HolderOfWrappers只能适用于任何类型的,不属于任何可能的类型建立了一个MyResource。我与HolderOfWrappers后我真的是这样的:

public struct HolderOfWrappers 
{ 
    let anyWrappedItem: MyResource<> 
} 

甚至MyResource<*> - 我想这个代码,我想,可以容纳任何类型MyResource的变量说。如果我尝试使用任何一种语法,我都会得到一个它期望的类型的编译器错误。

我可以只有anyWrappedItem类型Any,但然后你失去了类型信息供将来使用。我也不希望HolderOfWrapper是通用的(因为后来我只是有同样的问题)。

这几乎就像我试图把泛型类型作为anyWrappedItem存储变量的协议,不会因为其他原因工作...

+0

实际上似乎是同样的情况矿山这里 http://stackoverflow.com/questions/28250294/dictionary-with-string-as-key-and-generic-class-as-value 由于MyResource 和MyResource 似乎是完全无关的类形成编译器点的观点,你将不得不MyResource 像MyResourceBase somethinh。但是,那不适用于结构体.. – Alex 2015-02-09 10:57:18

+0

感谢您指出这一点,我没有在搜索中遇到这个问题 - 我宁愿使用基类而不是使用Any作为存储类型......它也是让我有我可以期待的方法签名。无论如何,这个结构是需要成为一个班级的边缘,叹息。 – 2015-02-09 17:53:46

回答

2

我想你可以通过在你的HolderOfWrappersinit方法中加入一个通用参数来做你想要的。基本上,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本身不是通用的,将填补anyWrappedItem一个MyResource<Any>持有相同的值,你在通过resource

+0

非常有趣,这似乎工作!我不介意资源的副本,因为它是一个结构体,并且无论如何都将被复制到整个地方。我很惊讶,虽然编译器不能正常工作,但我从外部设置的资源不是明确的“任何”,但可以从内部初始化完成同样的事情。也会试用Swift 1.2。 – 2015-02-09 22:10:25

1

这个怎么样

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 { }

+0

一个有趣的想法,但当你指出需要做扩展是有点烦人......但如果我传入MyResource的对象都实现某种协议,那可能是最好的主意。我会考虑这个... – 2015-02-09 18:15:57

+0

在进一步的实验中,我不确定这会起作用 - 即使我有一个符合Wrapper的结构,也可以使用这些更改,但无法将该类型的MyResource传递到holdResource调用中。它产生了一股向后的压力,所以所有的通用性都被删除了,最终MyResource只能使用一个Wrapper符合对象 - 然后我必须删除MyResource泛型类型声明才能使用它。 – 2015-02-09 18:50:44

相关问题