在 C++ 中,它会是这样的struct A
由...组成struct B
和一些功能B
获取指向父对象的指针A
。所以函数为A
调用该函数B
将简单地通过this
指向它的指针。我正在 Rust 中尝试此操作,但未能使其正常工作 - 这就是我想要实现的目标:
struct A<Type: T> {
composition: Type,
value: usize,
}
impl<Type> A<Type> where Type: T {
fn new(obj: Type) -> A<Type> {
A {
composition: obj,
value: 999,
}
}
fn f(&mut self) {
println!("Value: {:?}", self.value);
}
fn call(&mut self) {
self.composition.f(&mut self);
}
}
trait T {
fn f(&mut self, &mut A<Self>);
}
struct B {
value: usize,
}
impl B {
fn new() -> B {
B { value: 0, }
}
}
impl T for B {
fn f(&mut self, parent: &mut A<B>) {
println!("B::f");
parent.f();
}
}
fn main() {
let objA = A::new(B::new());
// I want call sequence -> A::call() -> B::f() -> A::f()
objA.call();
}
请注意,我要求所有函数都具有可变性,尽管在上面的示例中看起来似乎是这样&mut self
在大多数函数中参数没有多大意义。 Rust 是如何做到这一点的?
这是行不通的,因为你违反了可变别名要求 - 你试图可变地借用A
及其子结构同时:
self.composition.f(self);
// roughtly equivalent to:
let c = &mut self.composition; // borrow substructure
c.f(self /* borrow self */);
(我已经删除了明确的&mut self
因为它是不正确的(因为它给了你&mut &mut A<...>
,但它根本不会改变整个画面。)
这是 Rust 框架中的一个自然错误。假设f
对该特定组合物的实施X
重写composition
传递的对象上的字段:
impl T for X {
fn f(&mut self, a: &mut A<X>) {
a.composition = create_x_somehow();
}
}
突然,调用该方法的对象被销毁,并且self
已作废!
当然,编译器会阻止你这样做即使你知道你不修改的composition
,因为这种知识不能静态编码(特别是考虑到这是一种特征方法,任何有权访问您特征的人都可以实现)。
在这种情况下,你基本上有两种选择:
- 重新表述问题,使其不再需要这样的架构,或者
- 使用特殊的语言/库结构来解决此类静态检查。
第二点是关于使用诸如Cell
/RefCell
(它们是安全的,即不需要unsafe
块,但它们可能会在运行时出现恐慌 - 也许这些可以在您的情况下工作),或者,如果没有其他帮助,则放弃原始指针并unsafe
代码。但是,坦率地说,第一个选项通常更好:如果您根据编译器强制执行的所有权语义和别名规则来设计代码,那么最终的架构几乎总是具有更好的质量。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)