以下代码不能为我编译.
trait A {
fn fun0(&self);
fn fun2(&self) -> Option<Box<Self>>;
}
struct B0 {
id: usize,
}
impl A for B0 {
fn fun0(&self) { println!("Value: {:?}", self.id); }
fn fun2(&self) -> Option<Box<Self>> { Option::None }
}
struct B1 {
id: isize,
}
impl A for B1 {
fn fun0(&self) { println!("Value: {:?}", self.id); }
fn fun2(&self) -> Option<Box<Self>> { Option::Some(Box::new(B1 { id: self.id, })) }
}
enum C {
None,
Put { object: Box<A>, },
}
fn fun1(values: Vec<C>) {
for it in values.iter() {
match *it {
C::Put { object: ref val, } => val.fun0(),
C::None => (),
};
}
}
fn main() {
let obj_b0 = Box::new(B0 { id: 778, });
let obj_b1 = Box::new(B1 { id: -8778, });
let obj_c0 = C::Put { object: obj_b0, };
let obj_c1 = C::Put { object: obj_b1, };
let mut vec = Vec::new();
vec.push(obj_c0);
vec.push(obj_c1);
fun1(vec);
}
Run Code Online (Sandbox Code Playgroud)
给出错误:
cargo run
Compiling misc v0.0.1 (file:///home/spandan/virtualization/coding/my/rust-tests/misc/misc)
src/main.rs:188:48: 188:54 error: the trait `A` is not implemented for the type `A` [E0277]
src/main.rs:188 C::Put { object: ref val, } => val.fun0(),
^~~~~~
src/main.rs:197:35: 197:41 error: cannot convert to a trait object because trait `A` is not object-safe [E0038]
src/main.rs:197 let obj_c0 = C::Put { object: obj_b0, };
^~~~~~
src/main.rs:197:35: 197:41 note: method `fun2` references the `Self` type in its arguments or return type
src/main.rs:197 let obj_c0 = C::Put { object: obj_b0, };
^~~~~~
src/main.rs:198:35: 198:41 error: cannot convert to a trait object because trait `A` is not object-safe [E0038]
src/main.rs:198 let obj_c1 = C::Put { object: obj_b1, };
^~~~~~
src/main.rs:198:35: 198:41 note: method `fun2` references the `Self` type in its arguments or return type
src/main.rs:198 let obj_c1 = C::Put { object: obj_b1, };
^~~~~~
error: aborting due to 3 previous errors
Could not compile `misc`.
Run Code Online (Sandbox Code Playgroud)
与...合作
rustc --version
rustc 1.0.0-nightly (00978a987 2015-04-18) (built 2015-04-19)
Run Code Online (Sandbox Code Playgroud)
当fun2(&self)进入图片时出现问题.如果fun0是特征中唯一存在的函数,它编译并运行良好.但我的代码需要这样的模式 - 我该怎么做?
编辑:此处给出了上述正确答案(/sf/answers/2098980691/).但是我遇到了同样的问题,如果我删除了&self从函数签名(即,使其静态):
fn fun2() -> Option<Box<A>>
Run Code Online (Sandbox Code Playgroud)
现在的问题是什么?
正如您所注意到的,当您删除fun2方法时问题就会消失.让我们更仔细地看一下:
fn fun2(&self) -> Option<Box<Self>>;
Run Code Online (Sandbox Code Playgroud)
请注意,其输出类型包含Self,即实现特征的类型.例如,如果A实现String,它将是String:
impl A for String {
fn fun2(&self) -> Option<Box<String>> { ... }
}
Run Code Online (Sandbox Code Playgroud)
然而!使用特征对象,值的实际类型将被删除,我们对特征对象的唯一了解是它是一个实现特征的值,但我们不知道实现特征的实际类型.Trait对象方法是动态调度的,因此程序选择在运行时调用的实际方法.这些方法必须具有相同的行为,即接受相同大小(成对)的相同数量的参数并返回相同大小的值.如果某个方法Self在其签名中使用某个地方,例如fun2,它的实现将不会彼此兼容,因为它们需要对不同大小的值进行操作,因此这些方法无法统一.
这些方法(不能与特征对象一起使用)被称为对象不安全(或不对象安全).如果特征包含这样的方法,则它不能成为特征对象 - 它也被称为不是对象安全的.
我相信,有什么可行的,你可以让特质返回一个特质对象:
fn fun2(&self) -> Option<Box<A>>
Run Code Online (Sandbox Code Playgroud)
现在,对实际类型的依赖性被取消,并且该特征再次成为对象安全的.
| 归档时间: |
|
| 查看次数: |
1986 次 |
| 最近记录: |