通用约束类型默认值

考虑以下代码:

protocol JSONParserType {
    associatedtype Element
}

// MARK: - Entities
struct Item {}

// MARK: - Parsers
struct OuterParser<T: JSONParserType where T.Element == Item>: JSONParserType {
    typealias Element = Item
    let innerParser: T

    init(innerParser: T = InnerParser()) {
        self.innerParser = innerParser
    }
}

struct InnerParser: JSONParserType {
    typealias Element = Item
}

OuterParser有一个孩子解析器应该被限制在一个特定的类型。不幸的是,在初始化器(或属性定义本身)中提供默认值会导致编译器抛出“无法将类型'InnerParser'的默认参数值转换为类型'T'”。

如果删除默认值分配并仅实例化显式OuterParser提供InnerParser,则一切正常。

let outerParser = OuterParser(innerParser: InnerParser())

我的问题是,提供实际上满足约束的默认值的方法不起作用的原因是什么?

哈米什

问题在于实际的类型T不是由类定义的,而是由使用该类的代码定义的。因此,它将在您在类中进行任何操作之前(在实例或静态级别)进行定义。因此,您无法分配InnerParserT,因为T该点已被定义为给定类型,而这可能不是InnerParser

例如,让我们考虑您有另一个解析器结构:

struct AnotherParser: JSONParserType {
    typealias Element = Item
}

并假设您当前的代码已编译。现在考虑这样做时会发生什么:

let parser = OuterParser<AnotherParser>()

您已将通用类型定义为AnotherParser–但初始化程序将尝试分配InnerParser给您的属性(现在为类型AnotherParser)。这些类型不匹配,因此可能无法正常工作。

按照相同的逻辑,此实现也将不起作用:

struct OuterParser<T: JSONParserType where T.Element == Item>: JSONParserType {
    typealias Element = Item
    let innerParser: T

    init() {
        self.innerParser = InnerParser()
    }

    init(innerParser: T) {
        self.innerParser = innerParser
    }
}

由于无法保证泛型类型T将与相同InnerParser当然,您可以强制向下转换T-但如果类型不兼容,这只会使您的代码崩溃。

不幸的是,没有真正的解决方案可以解决这个问题。我认为最好的最佳选择可能是创建两个工厂方法来创建OuterParser实例。

enum Parser {
    static func createParser() -> OuterParser<InnerParser> {
        return OuterParser(innerParser:InnerParser())
    }
    static func createParser<T>(innerParser:T) -> OuterParser<T> {
        return OuterParser(innerParser:innerParser)
    }
}

let innerParser = Parser.createParser() // OuterParser<InnerParser>

let anotherParser = Parser.createParser(AnotherParser()) // OuterParser<AnotherParser>

我们在这里使用一个无大小写的枚举,以避免用额外的函数污染全局名称空间。

尽管这不是很迅速,但是出于这个原因,我也建议您重新考虑一下如何定义解析器的逻辑。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为通用类型分配默认值

来自分类Dev

如何使用ForeignId约束的默认值?

来自分类Dev

SQL Server日期数据类型默认值和约束

来自分类Dev

给定类型的更好默认值

来自分类Dev

AngularJS输入类型=数字默认值

来自分类Dev

如何获取类型的默认值?

来自分类Dev

Scala中类型参数的默认值

来自分类Dev

elementType道具类型验证默认值

来自分类Dev

使用Union类型设置默认值

来自分类Dev

使用默认值创建复合类型

来自分类Dev

AngularJS输入类型=数字默认值

来自分类Dev

iOS int类型默认值问题

来自分类Dev

MySQL数组类型和默认值

来自分类Dev

TextBoxFor: INumber 类型但默认值 = ""

来自分类Dev

设置参数的默认值和类型

来自分类Dev

SQL Server 2012:使用默认值检查约束

来自分类Dev

ForceType指令上的检查约束或默认值

来自分类Dev

Swift函数中可选通用参数的默认值

来自分类Dev

如何为通用参数赋予默认值?

来自分类Dev

定义VUE道具的默认类型和默认值

来自分类常见问题

默认值类型与属性的类型不匹配

来自分类Dev

如何为联合类型参数提供默认值而无需获取“可以使用其他约束子类型实例化”

来自分类Dev

从字典返回通用类型(否则返回默认通用值)

来自分类Dev

通用约束中的通用类型

来自分类Dev

通用约束中的通用类型

来自分类Dev

同类型的通用约束

来自分类Dev

未知模板类型的默认值或零值

来自分类Dev

是否可以更改值类型变量的默认值?

来自分类Dev

基本类型的std :: vector的默认值