Are inout variables of protocol type prohibited?

给你一囗甜甜゛ 提交于 2021-02-07 22:12:09

问题


The following code:

protocol SomeProtocol {}
class SomeClass: SomeProtocol {}

private func doSomethingWith(inout someVar: SomeProtocol) {}

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

doSomethingWith(&someGlobalVar)

produces the following error:

Cannot invoke 'doSomethingWith' with an argument list of type '(inout SomeClass)'

Changing the penultimate line to private var someGlobalVar: SomeProtocol = SomeClass() resolves the error.

Subj.


回答1:


When you assign a SomeClass instance to a variable while declaring, the variable type is inferred to be SomeClass. The same as writing

private var someGlobalVar: SomeClass = SomeClass()

However, when passing to an inout parameter, the function can assign another instance to that variable, e.g.

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

Now you have a type mismatch. The error you are seeing is Swift preventing you getting a similar problem.

In other words: if you are passing a variable to a function and you know that the function can assign any instance adopting SomeProtocol to that variable, you have to use a variable that can actually hold any instance adopting SomeProtocol:

private var someGlobalVar: SomeProtocol



回答2:


In addition to what @Sulthan said, there are two more possible solutions, depending on what your function needs to do.

You can make the function generic:

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

Now you can pass an instance of any class conforming to the protocol:

var someGlobalVar = SomeClass()
doSomethingWith(&someGlobalVar)

If you only work with instances of a class and the function only modifies properties of the object pointed-to by the instance, then you don't need an inout-parameter at all, since classes are reference types. You only need to mark the protocol as a "class protocol":

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"


来源:https://stackoverflow.com/questions/31960117/are-inout-variables-of-protocol-type-prohibited

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!