Return Class 符合协议

Return Class conform to protocol

例如,我有一个代表品牌的协议

我在这个例子中有两个 class,Jbl 和 Columbo 符合 Brand 协议

建造者建造了一些东西,最后 return Jbl 或 Columbo 的名字 class (在代码示例中使用 random 简化了构建内容)

在这个示例代码中,我们可以在打印结果中随机期待 Jbl Brand 或 Columbo Brand

但这不能编译错误:Protocol 'Brand' can only be used as a generic constraint because it has Self or associated type requirements

protocol Brand: AnyObject, Hashable {
    var name: String { get }
}

extension Brand {
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
    }

    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.name == rhs.name
    }
}

class Jbl: Brand {
    var name: String { "Jbl" }
}

class Columbo: Brand {
    var name: String { "Columbo" }
}

class Builder {
    func build() -> Brand {    // Protocol 'Brand' can only be used as a generic constraint because it has Self or associated type requirements
        if .random() {
            return Jbl()
        } else {
            return Columbo()
        }
    }
}

var builder = Builder()
print(builder.build().name)

问题是,对于 build(),您正在尝试 return 一种 Brand,但 HashableSelf 要求作为其一部分定义。这就是为什么您会收到有关“自我或关联类型要求”的错误。

一个可能的解决方案是使 Brand 不是 Hashable 本身,而是任何符合 Brand 的 class Hashable 将获得 Hashable 实现 for Brand:

protocol Brand: AnyObject {
    var name: String { get }
}

extension Brand where Self: Hashable {
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
    }

    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.name == rhs.name
    }
}

但是,访问 build() 不会给您 hashValue,因为只有 class 符合 Brand HashablehashValue.

要解决此问题,请使 JblColumbo 符合 Hashable 协议。然后在 Builder class 中添加这样的函数 例如:

func getHashValue() -> Int {
    if .random() {
        return Jbl().hashValue
    } else {
        return Columbo().hashValue
    }
}

被称为:

print(builder.getHashValue())
// Prints: -8479619369585612153

显然,每次重新启动应用程序时,此哈希值都会发生变化,因此不要依赖它来持久保存数据。

并且仅出于样式原因:您可能更喜欢使用以下内容并使 classes 仅符合 HashableBrand:

typealias HashableBrand = Brand & Hashable