【问题标题】:Make instance of struct with a generic when the generic has a default value当泛型具有默认值时,使用泛型创建结构实例
【发布时间】:2020-10-26 07:55:50
【问题描述】:

我想将ListStyle 存储在SupportOpts 内的属性中,因此我将<S> 和where S: ListStyle 添加到结构声明中(来自此answer)。

struct SupportOpts<S> where S: ListStyle {
    var title: String = "Placeholder"
    var listStyle: S = InsetGroupedListStyle() as! S /// had to put an `as! S` or else it couldn't compile
}

我可以这样创建一个实例:

let options: SupportOpts = SupportOpts(
    title: "Title",
    listStyle: InsetGroupedListStyle()
)

但是,当我删除InsetGroupedListStyle() 时(我已经在SupportOpts 中设置了默认值):

let options: SupportOpts = SupportOpts(
    title: "Title"
)

我明白了:

无法推断泛型参数“S”,显式指定泛型参数以解决此问题 [修复]

所以我按下了“修复”按钮,现在它正在等待 S: ListStyle:

我应该在这里放什么?

let options: SupportOpts = SupportOpts<ListStyle>(title: "Title")
/// Error: Value of protocol type 'ListStyle' cannot conform to 'ListStyle'; only struct/enum/class types can conform to protocols

let options: SupportOpts = SupportOpts<S>(title: "Title")
/// Error: Cannot find type 'S' in scope (well that's kind of obvious...)

let options: SupportOpts = SupportOpts<InsetGroupedListStyle>(title: "Title")
/// this works...

我是否必须指定SupportOpts&lt;InsetGroupedListStyle&gt;(title: "Title"),即使我已经在SupportOpts 中设置了默认值?

【问题讨论】:

    标签: ios swift generics


    【解决方案1】:

    当您需要添加as! 时,您可以知道出现了问题。这不是正确的做法。考虑一下如果有人选择了不同的S:

    let options = SupportOpts<InsetListStyle>(title: "Title")
    

    这将不得不崩溃。

    相反,您需要一个扩展来让事情变得更方便。

    struct SupportOpts<S> where S: ListStyle {
        var title: String = "Placeholder"
        var listStyle: S     // No default value here
    }
    

    您的目标是拥有一个仅带有标题的init,因此您可以添加:

    extension SupportOpts where S == InsetGroupedListStyle {
        init(title: String) {
            self.init(title: title, listStyle: InsetGroupedListStyle())
        }
    }
    

    类型推断将解决剩下的问题:

    let options = SupportOpts(title: "Title")
    

    【讨论】:

    • 但是如果我有另一个包含var options: SupportOpts 的结构(只是类型,没有初始化)怎么办?它不起作用...我得到“对泛型类型 'SupportOpts' 的引用需要 <...> 中的参数”
    • 好的,我用struct OtherStruct&lt;S&gt;: View where S: ListStyle { var options: SupportOpts&lt;S&gt; } 修复了它,但不确定这是否正确
    • 是的,没错。你也可以写struct OtherStruct&lt;S: ListStyle&gt;: View。两者是相同的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 2020-04-03
    • 2018-09-12
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多