【问题标题】: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 变量在设计架构时并不是很受欢迎的选择;)
  • 没错,而且是为了更好。纯类协议很好地解决了这个问题,但并不明显。

标签: swift swift2 xcode7-beta5


【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-27
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多