2015-02-09 26 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

相關問題