在实现的特征之间更改对象类型

时间:2019-01-03 07:38:54

标签: rust

我想做什么:

我想在rust中创建一个小型解析器,它可以解码几种类型->数字,字符串,列表等。例如,列表可以包含任何类型->其他列表,数字等

我如何尝试:

我有一个超级特征'Element',它将成为我所有类型的基础。然后每种类型都有一个特征,所有特征都需要'Element'特征。这些特征得到一些具体结构的支持。由于列表可以包含(混合)任何类型,因此我尝试将值存储为Vec<Box<dyn Element>>。问题是,稍后我尝试将dyn Element转换为其他特征时,碰壁了:

错误:

error[E0161]: cannot move a value of type dyn Element: the size of dyn Element cannot be statically determined
  --> src/main.rs:94:27
   |
94 |     let boxed_as_number = num_as_element.to_boxed_number();
   |                           ^^^^^^^^^^^^^^

MCVE

use std::fmt;

pub enum ElementType {
    Number,
    Text,
}

pub trait Element: fmt::Debug {
    fn element_type(&self) -> ElementType;

    // Works, but I do not want a reference -> I want to change the "type"
    fn to_number_ref(&self) -> Option<&dyn Number>;

    fn to_boxed_number(self) -> Option<Box<dyn Number>>;
}

pub trait Number: Element {
    fn value(&self) -> i64;
}

pub trait Text: Element {
    fn value(&self) -> &str;
}

#[derive(Debug)]
pub struct SignedNumber {
    value: i64
}

impl SignedNumber {
    fn new(value: i64) -> SignedNumber {
        return SignedNumber { value };
    }
}

impl Element for SignedNumber {
    fn element_type(&self) -> ElementType {
        return ElementType::Number;
    }

    fn to_number_ref(&self) -> Option<&dyn Number> {
        return Some(self);
    }

    fn to_boxed_number(self) -> Option<Box<Number>> {
        return Some(Box::new(self));
    }
}

impl Number for SignedNumber {
    fn value(&self) -> i64 {
        return self.value;
    }
}

#[derive(Debug)]
pub struct StringWrapper {
    value: String
}

impl StringWrapper {
    fn new<T: Into<String>>(value: T) -> StringWrapper {
        return StringWrapper { value: value.into() };
    }
}

impl Element for StringWrapper {
    fn element_type(&self) -> ElementType {
        return ElementType::Text;
    }

    fn to_number_ref(&self) -> Option<&dyn Number> {
        return None;
    }

    fn to_boxed_number(self) -> Option<Box<Number>> {
       return None;
    }
}

impl Text for StringWrapper {
    fn value(&self) -> &str {
        return &self.value;
    }
}

fn main() {
    let num = SignedNumber::new(1);
    let num_as_element: Box<dyn Element> = Box::new(num);
    let borrowed_as_num = num_as_element.to_number_ref().unwrap();

    let num = SignedNumber::new(2);
    let num_as_element: Box<dyn Element> = Box::new(num);
    let boxed_as_number = num_as_element.to_boxed_number();
}

为什么

在这种情况下,self是否应该SignedNumber?为什么rustc认为它是dyn Element

impl Element for SignedNumber {
    fn to_boxed_number(self) -> Option<Box<Number>> {
        return Some(Box::new(self));
    }
}

是否可以进行这种类型转换,还是应该坚持引用?

0 个答案:

没有答案