协议类型的 inout 变量是不是被禁止?

Posted

技术标签:

【中文标题】协议类型的 inout 变量是不是被禁止?【英文标题】:Are inout variables of protocol type prohibited?协议类型的 inout 变量是否被禁止? 【发布时间】:2015-08-12 08:39:43 【问题描述】:

以下代码:

protocol SomeProtocol 
class SomeClass: SomeProtocol 

private func doSomethingWith(inout someVar: SomeProtocol) 

private var someGlobalVar = SomeClass() // inferring SomeClass's type

doSomethingWith(&someGlobalVar)

产生以下错误:

无法使用“(inout SomeClass)”类型的参数列表调用“doSomethingWith”

将倒数第二行更改为private var someGlobalVar: SomeProtocol = SomeClass() 可解决错误。

主题

【问题讨论】:

我很惊讶这个问题没有更多的观点!似乎更多的人会遇到......再一次,也许人们不再通过带有协议参数的函数来改变对象。 :) @RayToal 可能是因为inout 变量在设计架构时并不是很受欢迎的选择;) 没错,而且是为了更好。纯类协议很好地解决了这个问题,但并不明显。 【参考方案1】:

除了@Sulthan 说的,还有两种可能的解决方案, 取决于您的功能需要做什么。

你可以使函数通用

func doSomethingWith<T : SomeProtocol>(inout someVar: T) 

现在您可以传递任何符合协议的类的实例:

var someGlobalVar = SomeClass()
doSomethingWith(&someGlobalVar)

如果你只使用 class 的实例并且只使用函数 修改实例指向的对象的属性,那么您根本不需要 inout 参数,因为类是引用类型。 您只需要将协议标记为“类协议”:

protocol SomeProtocol : class 
    var name : String  get set 

class SomeClass: SomeProtocol 
    var name : String = ""


func doSomethingWith(someVar: SomeProtocol) 
    // Modify the object:
    someVar.name = "modfied"


var someGlobalVar = SomeClass()
doSomethingWith(someGlobalVar)
print(someGlobalVar.name) // "modified"

【讨论】:

【参考方案2】:

当您在声明时将SomeClass 实例分配给变量时,变量类型被推断为SomeClass。和写一样

private var someGlobalVar: SomeClass = SomeClass()

但是,当传递给inout 参数时,函数可以为该变量分配另一个实例,例如

private func doSomethingWith(inout someVar: SomeProtocol) 
    someVar = OtherClass()

现在你有一个类型不匹配。您看到的错误是 Swift 阻止您遇到类似问题。

换句话说:如果您将变量传递给函数并且您知道该函数可以将采用SomeProtocol 的任何实例分配给该变量,那么您必须使用一个实际上可以容纳任何采用SomeProtocol 的实例的变量:

private var someGlobalVar: SomeProtocol

【讨论】:

以上是关于协议类型的 inout 变量是不是被禁止?的主要内容,如果未能解决你的问题,请参考以下文章

FPGA中的inout类型的数据在引脚分配的时候与input和output类型有区别吗?望高手赐教!

无法使用类型为 '(inout inout $T6, inout inout$T11) 的参数列表调用 'subscript'

Java JDBC调用inout类型参数的存储过程

swift 无法将类型“[Liquor]”的值转换为预期的参数类型“inout _”

无法将“Int”类型的值转换为预期的参数类型“(inout UnsafeMutableBufferPointer<_>, inout Int) throws -> Void”

oracle存储过程