我有一个协议及其扩展,以及一个符合协议的类。
for /f "skip=3 delims=\" %%A in ('net view ^| findstr /v /C:"The command completed successfully"') do Echo %%A
现在如果我想让两个战士战斗:
protocol WarAbilities {
var strength: Int { get set }
func attack(inout opponent: WarAbilities)
}
extension WarAbilities {
func attack(inout opponent: WarAbilities) {
opponent.strength -= 1
}
}
class Warrior: WarAbilities {
var strength: Int
init(strength: Int) {
self.strength = strength
}
}
我收到此错误消息:
错误:无法将“WarAbilities”类型的不可变值作为inout参数
传递
添加let thug1 = Warrior(strength: 10)
let thug2 = Warrior(strength: 30)
thug1.attack(&thug2)
看起来很有希望:
mutating
但是编译器也不开心,我无法理解新错误消息的含义:
错误:无法将不可变值作为inout参数传递:从“Warrior”到“WarAbilities”的隐式转换需要暂时的
由于protocol WarAbilities {
var strength: Int { get set }
mutating func attack(inout opponent: WarAbilities)
}
extension WarAbilities {
mutating func attack(inout opponent: WarAbilities) {
opponent.strength -= 1
}
}
符合Warrior
我认为其中一个可行 - 但看起来Swift没有这种...协方差?我甚至不确定我在这里谈论的是什么。
我的错误是什么?
答案 0 :(得分:3)
使其成为class
协议并摆脱(然后)不必要的inout
内容:
protocol WarAbilities : class {
var strength: Int { get set }
func attack(opponent: WarAbilities)
}
extension WarAbilities {
func attack(opponent: WarAbilities) {
opponent.strength -= 1
}
}
class Warrior: WarAbilities {
var strength: Int
init(strength: Int) {
self.strength = strength
}
}
let thug1 = Warrior(strength: 10)
let thug2 = Warrior(strength: 30)
thug1.attack(thug2)
thug2.strength // 29
(事实上我不清楚为什么你需要一个协议;因为Warrior是一个类,你可以让WarAbilities成为它的超类。)
答案 1 :(得分:2)
我认为有两件事是错的:
let
- 常量传递给inout
inout
请注意,在您的示例中,您甚至不需要 (请参阅matt的正确处理此问题的答案)inout
,因为您没有覆盖参数,而是该参数的某些实例成员。简单地删除inout
可能会对你的情况起作用,因为根本不需要它。
其次请注意,使用mutating
可能对你没有任何好处,因为那只是讨论变异自己的成员,而不是参数的成员。
问题解释:
让我们考虑一个产生完全相同问题输出的更简单的问题:
protocol A {}
class B : A {}
func c(inout d : A) {}
let a = B()
c(&a)
首先不起作用,因为a
是一个常数。因此,请将let
更改为var
然后编译器抱怨要求临时。这是一个非常令人困惑的错误消息,但问题实际上是有道理的。
您无法将某些类型的子类型传递给inout
,或将某些协议的实现传递给期望协议的inout
说明 - 请考虑以下示例:
class A {}
class B : A {}
func c(inout a : A) { a = A() }
如果您通过
调用该方法会发生什么var b = B()
c(&b)
b
会被更改,现在与a
相同 - 但a
不属于B
,b
据说是var b : A = B()
c(&b)
请注意,以下内容将再次起作用:
B
我们传递A
,但实际上只担心它是protocol P {}
class K : P {}
class X : P {}
func f(inout p : P) { p = X() }
var k = K()
f(&k) // does not work
var p : P = K()
f(&p) // works
。协议也是如此:
{{1}}
答案 2 :(得分:0)
支持协议支持:
protocol IPositional{
func setPosition(position:CGPoint)
}
extension IPositional{
var positional:IPositional {get{return self as IPositional}set{}}
}
class A:IPositional{
var position:CGPoint = CGPoint()
func setPosition(position:CGPoint){
self.position = position
}
}
func test(inout positional:IPositional){
positional.setPosition(CGPointMake(10,10))
}
var a = A()
test(&a.positional)
a.position//(10.0, 10.0)
<强>结论:强>
这样做的好处是:你现在可以拥有一个&#34; inout方法&#34;对于实现IPositional