问题
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