Swift中遵循继承协议的实例作为inout参数传参编译报错问题
错误原因
inout参数要求传入变量的静态类型和参数声明类型完全一致,不支持隐式的协议向上转换。你代码中变量s的静态类型是SportsCar,而test_car的参数类型是inout Car,类型不匹配因此触发编译错误。- 非
inout场景下支持隐式向上转换是因为参数只读,不会修改原变量的类型;但inout参数可读可写,函数内部可以给参数赋值任意遵守Car协议的实例,如果允许SportsCar类型变量传入,赋值后可能违反原变量的SportsCar类型约束,编译器为了保证类型安全直接禁止了这种隐式转换。 - 你当前的代码还存在一个低级错误:
inout参数传参时必须添加&符号,原调用写法test_car(car: s )哪怕类型匹配也会编译失败。
解决方案
方案1:修改变量静态类型
如果业务中不需要使用s的SportsCar专属属性/方法,直接把s的声明类型改为Car即可:
// 原声明:var s: SportsCar var s: Car
调用时添加&符号:
test_car(car: &s)
方案2:临时类型转换
如果需要保留s的SportsCar类型,可以临时转换为Car类型传入函数,执行完成后再转回SportsCar:
func run() { print("Running Test") var temp: Car = s test_car(car: &temp) s = temp as! SportsCar // 已知temp原始类型为SportsCar,可安全强转 print("Finished Test") }
方案3:使用泛型约束(最推荐)
给test_car添加泛型约束,让它支持所有遵守Car协议的类型,不需要修改原有变量类型也不需要手动转换:
// 修改函数声明 func test_car<T: Car>(car: inout T) { print("Car has \(car.wheels) wheels") car.wheels += 1 print("Wheel added") print("Car now has \(car.wheels) wheels\n") }
调用时直接传&s即可正常运行:
test_car(car: &s)
内容的提问来源于stack exchange,提问作者Jonathan Stanley-Smith
相关产品推荐
相关产品推荐

