【发布时间】:2019-02-16 17:30:06
【问题描述】:
我无法理解盒装特征的值是如何产生的。考虑以下代码:
trait Fooer {
fn foo(&self);
}
impl Fooer for i32 {
fn foo(&self) { println!("Fooer on i32!"); }
}
fn main() {
let a = Box::new(32); // works, creates a Box<i32>
let b = Box::<i32>::new(32); // works, creates a Box<i32>
let c = Box::<dyn Fooer>::new(32); // doesn't work
let d: Box<dyn Fooer> = Box::new(32); // works, creates a Box<Fooer>
let e: Box<dyn Fooer> = Box::<i32>::new(32); // works, creates a Box<Fooer>
}
显然,变体 a 和 b 可以正常工作。但是,变体 c 没有,可能是因为 new 函数只接受相同类型的值,而自 Fooer != i32 以来情况并非如此。变体 d 和 e 工作,这让我怀疑正在执行某种从 Box<i32> 到 Box<dyn Fooer> 的自动转换。
所以我的问题是:
- 这里是否发生了某种转换?
- 如果是这样,它背后的机制是什么,它是如何工作的? (我也对底层细节感兴趣,即在幕后如何表示东西)
- 有没有办法直接从
i32创建Box<dyn Fooer>?如果没有:为什么不呢?
【问题讨论】:
-
我问自己,你为什么想要
Box<Fooer>。我想你不太明白,特征在 Rust 中是如何工作的。尝试在每个变量 (a..e) 上调用.foo(),看看会发生什么。 -
编译器告诉你确切的原因,为什么
c不起作用:the method 'new' exists but the following trait bounds were not satisfied: 'Fooer : std::marker::Sized' -
这是另一个关于方差的问题。我很抱歉,但我无能为力:这种事情仍然会触发我:P
-
@hellow:关于错误消息:这似乎暗示它实际上无法调用
Box::<Fooer>::new,因为给定的类型参数必须具有在编译时已知的大小,而Fooer之后的情况并非如此是一种特质,对吧?所以我的假设是正确的,你必须先构造一个大小类型的 Box,然后以某种方式将其转换为 trait 类型的 Box,这会给我留下我最初的问题:这种转换是如何/通过什么机制发生的? -
@Boiethios AFAIU Variance 仅限于 Rust 的生命周期,因为 trait 和实现结构之间没有子类型关系。没有“结构继承”。否则,鉴于
Box<T>是T的变体,我可以将Box<Box<i32>>转换为Box<Box<Fooer>>。另一方面,将Box<Box<&'a i32>>转换为Box<Box<&'b Fooer>>其中'a : 'b是可能的,因为'a : 'b与i32: Fooer不同,是实际的子类型关系,并且不可变借用&'x T不仅是T的变体,而且也超过'x。
标签: rust polymorphism traits boxing representation