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

Swift带默认值初始化器调用歧义,求非修改式解决方法

解决Swift初始化器调用歧义的实用方法

我写的类里有两个结构相近的初始化器:

public init(
        contentInsets: MyInsets = .init(vertical: .level0, horizontal: .level6),
        midToLeftSpacing: CGFloat = 0,
        rightToMidSpacing: CGFloat = 0
)

public init(
        contentInsets: MyInsets = .init(vertical: .level0, horizontal: .level6),
        midToLeftSpacing: MyInsetLevel = .level0,
        rightToMidSpacing: MyInsetLevel = .level0
)

当我用下面的方式调用时,编译器没法判断该选哪一个,直接报 Ambiguous use of 'init' 错误:

YourClassName(
    vertical: .level0,
    left: .level22,
    right: .level0
)

虽然改初始化器或者加带默认值的参数能搞定,但总觉得不太合理,有没有不用改原代码就能指定调用哪个初始化器的办法?


1. 显式声明参数类型

直接给参数加上类型标注,让编译器一眼锁定目标初始化器:

调用接受CGFloat的版本

YourClassName(
    contentInsets: MyInsets(vertical: .level0, horizontal: .level22),
    midToLeftSpacing: CGFloat(0),
    rightToMidSpacing: CGFloat(0)
)

调用接受MyInsetLevel的版本

YourClassName(
    contentInsets: MyInsets(vertical: .level0, horizontal: .level22),
    midToLeftSpacing: MyInsetLevel.level0,
    rightToMidSpacing: MyInsetLevel.level0
)

2. 用临时变量辅助类型推断

如果不想写全类型名,可以先定义对应类型的临时变量,再传入参数:

let targetSpacing: MyInsetLevel = .level0
YourClassName(
    contentInsets: MyInsets(vertical: .level0, horizontal: .level22),
    midToLeftSpacing: targetSpacing,
    rightToMidSpacing: targetSpacing
)

或者直接在参数里做类型转换,更简洁:

YourClassName(
    contentInsets: MyInsets(vertical: .level0, horizontal: .level22),
    midToLeftSpacing: .level0 as MyInsetLevel,
    rightToMidSpacing: .level0 as MyInsetLevel
)

3. 利用初始化器引用明确指定

如果需要把初始化器作为参数传递,或者想更清晰地指定版本,可以用初始化器引用的方式:

// 绑定接受CGFloat的初始化器
let cgFloatInitializer: (MyInsets, CGFloat, CGFloat) -> YourClassName = YourClassName.init
let instance1 = cgFloatInitializer(MyInsets(vertical: .level0, horizontal: .level22), 0, 0)

// 绑定接受MyInsetLevel的初始化器
let levelInitializer: (MyInsets, MyInsetLevel, MyInsetLevel) -> YourClassName = YourClassName.init
let instance2 = levelInitializer(MyInsets(vertical: .level0, horizontal: .level22), .level0, .level0)

这些方法都不需要修改原有的初始化器代码,通过显式指定参数类型或初始化器引用,就能让编译器明确你要调用的版本,完美解决歧义问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:45:32