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

Swift中用无要求协议扩展存通用函数的优劣分析

无约束协议扩展存储通用函数的技术方案优劣分析

我发现一种Swift编码用法:仅通过无约束、无关联类型的协议+协议扩展来存放通用函数,这些函数仅调用全局符号或依赖输入参数,原本完全可以实现为具体类型的静态函数(甚至命名空间式的静态类型)。这类协议除了扩展里提供的默认实现函数外,没有任何协议要求或约束。

示例代码(协议扩展实现)

protocol Naming {
    func fetchName() -> String
}

extension Naming {
    func fetchName() -> String {
        // 具体实现不影响核心逻辑,仅调用全局对象或依赖参数
        // 本质上这段代码完全可以放在某个具体类型的静态方法中
        return NotificationCenter.default.description
    }
}

要调用这类函数,必须让目标类型遵循该协议,再通过self调用:

class Road: Naming {
    func logName() {
        print(fetchName())
    }
}

对比常规实现(静态函数/命名空间)

与之相对的常规实现是,把这类函数放在具体类型的静态方法中,甚至可以用一个空结构体作为命名空间:

struct Name {
    static func fetchName() -> String {
        return NotificationCenter.default.description
    }
}

对应的调用方式:

class Street {
    func logName() {
        print(Name.fetchName())
    }
}

劣势

你总结的几点劣势非常准确:

  • 产生冗余代码:为了获取本可以作为全局/静态函数的功能,需要额外定义协议、让类型遵循协议,增加了不必要的样板代码
  • 过度使用协议模式:明明通过组合(直接调用静态函数)就能满足需求,却强制使用协议遵循的模式,违背了"组合优于继承"的设计原则
  • 性能损耗:协议方法默认是动态派发,相比静态函数的静态派发会带来一定的性能开销

潜在优势

虽然这种用法看起来弊端明显,但在某些特定场景下可能存在微弱优势:

  • 语法便捷性:如果某个类型需要批量接入多个这类通用功能,通过遵循多个协议,可以直接在类型内部用self.调用所有协议扩展方法,相比每次写Namespace.function()少了一些字符输入
  • 后续扩展空间:虽然当前协议没有任何约束,但未来如果需要给这类函数增加类型相关的逻辑,可以直接在协议中添加要求,而不需要修改所有调用点——不过这种场景非常罕见,因为原本的设计就是无约束的通用函数
  • 语义分组:相比全局函数,协议可以将功能语义上相关的函数分组,让类型遵循协议相当于"声明该类型具备某一类能力",在代码可读性上有极其微弱的提升(但这种语义提升完全可以通过命名空间实现)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:13:20