You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift扩展通用协议适配:如何让.set(to:)覆盖更多类型及排除条件?

解答你的Swift扩展问题

问题1:让.set(to:)覆盖更多类型,无需重复实现

首先得说,你之前给Equatable加扩展其实是个误区——这个set(to:)方法根本不需要依赖Equatable协议!赋值操作variable = self只要求左右类型一致,和是否能比较完全无关。

要让这个方法支持所有类型,只需要去掉协议约束,直接给所有类型添加扩展就好:

extension Any {
    @discardableResult
    public func set(to variable: inout Self) -> Self {
        variable = self
        return self
    }
}

或者更严谨的写法(效果和上面一致,因为所有类型都隐式遵循Any):

extension Self {
    @discardableResult
    public func set(to variable: inout Self) -> Self {
        variable = self
        return self
    }
}

这样修改后,不管是遵循Equatable的基础类型(比如Int、String),还是不遵循的自定义类型(比如你自己写的未实现==的struct或class),都能调用.set(to:)方法,而且只需要实现一次,完全不会有重复提示的问题。

举个实际使用的例子:

// 自定义不遵循Equatable的类型
struct MyType {
    var value: Int
}

var myVar = MyType(value: 0)
let newValue = MyType(value: 100)

// 一行完成赋值并返回值
let returnedValue = newValue.set(to: &myVar)
print(myVar.value) // 输出100
print(returnedValue.value) // 输出100

问题2:Swift扩展中是否支持排除式where子句?

很遗憾,在你使用的Swift 4.1(以及后续直到当前的Swift版本)中,不支持直接用!来写排除条件的where子句,比如你提到的extension Equatable where !(Element: CustomStringConvertible)这种语法是不合法的。

不过我们可以用间接方式实现类似“排除”的效果,利用Swift扩展的优先级规则:更具体的扩展会覆盖更通用的扩展。

举个例子,如果你想给所有Equatable类型加一个方法,但排除那些同时遵循CustomStringConvertible的类型,可以这么做:

  1. 先给所有Equatable类型添加默认实现:
extension Equatable {
    func myMethod() {
        print("这是给所有Equatable类型的默认实现")
    }
}
  1. 再给同时遵循Equatable和CustomStringConvertible的类型添加一个空实现(或者你想要的特殊逻辑):
extension Equatable where Self: CustomStringConvertible {
    func myMethod() {
        // 空实现或自定义逻辑,会覆盖上面的默认实现
    }
}

这样一来,同时遵循两个协议的类型调用myMethod()时,会使用第二个扩展的实现;其他Equatable类型则会使用第一个扩展的实现,间接达到了“排除”CustomStringConvertible类型的效果。


内容的提问来源于stack exchange,提问作者Noah Wilder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:46:45