传入协议类型时出现错误“Inout argument can be set to a value with a type other than ...”

问题描述 投票:0回答:2

我从 C++ 转向 Swift。我在协议和结构方面遇到了这种情况(我正在使用随机数):
(1) 协议

RandomPr
指定有一些方法,例如
randFloat()
返回 0 到 1 之间的 Float。
(2) 使用“真实”随机数生成器实现
RandomS
的结构体
RandomPr

(3) 一个 struct
FakeRandomS
,它实现了
RandomPr
,但具有其他方法,例如
loadFloat()
来加载 Float 数组,然后当我在
randFloat()
实例上调用
FakeRandomS
时,这些 Float 数组会被反刍。 (用于测试目的。)

现在我有一个函数

DoSomething(rng: inout RandomPr)
,我想将其与
RandomS
FakeRandomS
一起使用。该参数必须是输入输出,因为我需要更新 RNG(无论是真还是假)。使用
DoSomething
的实例调用
RandomS
没有问题。

但是如果我这样做

var fakeRng = FakeRandomS()
fakeRng.loadFloat([0.1, 0.2, 0.3])
DoSomething(rng: &fakeRng)

我收到错误“Inout 参数可以设置为“FakeRandomS”以外类型的值。建议的修复是将

fakeRng
定义为

var fakeRng: RandomPr = FakeRandomS()

但是现在尝试在

loadFloat
上调用
fakeRng
会失败,因为
RandomPr
没有方法
loadFloat
,并且编译器看不到
fakeRng
有方法。

我尝试制作另一个协议

FakeRandomPr
,其中包含
FakeRandomS
具有的额外方法,并定义

var fakeRng: RandomPr & FakeRandomPr = FakeRandomS()

但是,令人沮丧的是,我现在再次收到“Inout argument can be set to a value with a type other not ...”错误。

我可以在 C++ 中毫无问题地执行与此相同的操作(一个纯抽象基类和两个子类,通过引用传递),并且我想传递的其中一个内容是否有额外的方法并不重要。我想将其转换为协议和结构。 Swift 解决方案是什么?

swift swift-protocols inout
2个回答
1
投票

Swift 解决方案是什么?

您可能需要使用泛型:

func doSomething<RP: RandomPr>(rng: inout RP) {
    //...
}

Swift 不仅仅是 C++ 的另一种语法,更好地以 Swifty 的方式思考。


0
投票

好的 - 我不久前发布了这个。现在我回过头来,并获得了一些理解,感谢 Hamish 在 Why do we need a generic here? 中的回答?协议还不够吗?.

我没有意识到,使用以协议形式给出类型的 inout 参数,整个输入对象可以被替换为完全不同类型的对象(在 Hamish 的示例中, struct Foo 类型的对象被 struct Bar 类型的对象替换) )。如果我随后使用该对象,除了它满足协议之外,我无法假设它的任何内容。

迟来的感谢哈米什。

© www.soinside.com 2019 - 2024. All rights reserved.