![](/img/trans.png)
[英]How do you convert a Box<dyn Trait> to a Rc<dyn Trait>?
[英]How to cast to dyn Trait when creating a Box<dyn Trait>
在以下代碼中:
trait Animal {}
struct Dog {}
impl Animal for Dog {}
fn main() {
// first two lines are OK as expected
let _animal1: Box<dyn Animal> = Box::new(Dog {});
let _animal2: Box<dyn Animal> = Box::new(Dog {}) as Box<dyn Animal>;
// next line is a compile error: cast to unsized type: `Dog` as `dyn Animal`
let _animal3: Box<dyn Animal> = Box::new(Dog {} as dyn Animal);
}
為什么將Dog{}
轉換為dyn Animal
會出錯?
對於這個例子,編譯器正確地推斷出類型並且轉換是多余的。 但是對於一般情況,應該使用什么來向編譯器而不是dyn Animal
提供類型信息。
以不同的方式向 state 提問:如果 object 不是dyn Animal
,它是什么類型的Box::new()
?
我的理解是,每個對 object 的引用(例如&T
、 &mut T
、 Box<T>
、 Arc<T>
等)都可以在不知道 object 的大小(例如滿足Sized
特征)的情況下存在。 示例中的前兩行就是這種情況。
但是,在第三行中,您簡要地(在將其傳遞給Box::new()
之前)將其轉換為dyn Animal
,這不是引用,而是 object。Rust 中存在的每個 object 都需要具有已知大小,否則 Rust 將不知道在堆棧上為其分配多少空間。 這不是引用的問題,因為引用具有獨立於它們所引用的 object 的恆定大小。
考慮一下:
let dog = Dog{};
// Works
let _animal : &dyn Animal = &dog as &dyn Animal;
// Fails
let _animal : dyn Animal = dog as dyn Animal;
我認為錯誤消息非常具有解釋性:
error[E0620]: cast to unsized type: `Dog` as `dyn Animal`
--> src/main.rs:13:32
|
13 | let _animal : dyn Animal = dog as dyn Animal;
| ^^^^^^^^^^^^^^^^^
|
help: consider using a box or reference as appropriate
--> src/main.rs:13:32
|
13 | let _animal : dyn Animal = dog as dyn Animal;
| ^^^
For more information about this error, try `rustc --explain E0620`.
你問題的第二部分是“我應該用什么把狗變成動物?”。
我會回答:這取決於你是否想繼承所有權。
如果您不想繼承所有權而是保留原始 object:
let dog = Dog{};
let animal: &dyn Animal = &dog;
否則,如果您想將所有權轉移到動物 object 中:
let dog = Dog{};
let animal: Box<dyn Animal> = Box::new(dog);
正如編譯器所說,您不能轉換為dyn
類型,因為它未調整大小。 也就是說,堆棧中不能存在dyn T
類型的值。
您只能在類似指針的構造后面使用dyn
類型,例如&dyn _
或Box<dyn _>
,因為額外的間接級別意味着dyn
object 本身不存在,它只是類型系統的構造。
那些自動處理內部轉換。 正如您所注意到的,您不需要顯式強制轉換,強制轉換是隱式的。
這些類似於指針的類型通過神奇的CoerceUnsized
特性(仍然不穩定)進行轉換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.