繁体   English   中英

返回结果<Box<dyn Trait> &gt; 在比赛中

[英]Return Result<Box<dyn Trait>> in a match

我有一组实现给定特征的类型,我想从字符串名称中获取一个具体的类型对象,奇怪的是当我的match返回Box<dyn Trait>时它可以工作,但当我将它包装在Result时它不会。

鉴于此特征和类型:

trait Shape {
    fn edges(&self) -> u8;
}

struct Triangle {}

impl Shape for Triangle {
    fn edges(&self) -> u8 {
        3
    }
}

struct Rectangle {}

impl Shape for Rectangle {
    fn edges(&self) -> u8 {
        4
    }
}

这有效:

fn get_shape_edges(name: &str) -> Result<u8, &str> {
    let shape: Box<dyn Shape> = match name {
        "triangle" => Box::new(Triangle {}),
        "rectangle" => Box::new(Rectangle {}),
        _ => panic!("Bad value"),
    };
    Ok(shape.edges())
}

但是,这不会:

fn get_shape_edges(name: &str) -> Result<u8, &str> {
    let shape: Box<dyn Shape> = match name {
        "triangle" => Ok(Box::new(Triangle {})),
        "rectanble" => Ok(Box::new(Rectangle {})),
        _ => Err("bad value")
    }?;
    Ok(shape.edges())
}

错误:

error[E0308]: `match` arms have incompatible types
  --> src/main.rs:24:24
   |
22 |       let shape: Box<dyn Shape> = match name {
   |  _________________________________-
23 | |         "triangle" => Ok(Box::new(Triangle {})),
   | |                       ------------------------- this is found to be of type `Result<Box<Triangle>, _>`
24 | |         "rectanble" => Ok(Box::new(Rectangle {})),
   | |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Triangle`, found struct `Rectangle`
25 | |         _ => Err("bad value")
26 | |     }?;
   | |_____- `match` arms have incompatible types
   |
   = note: expected type `Result<Box<Triangle>, _>`
              found enum `Result<Box<Rectangle>, _>`

当然这只是一个例子,在我的代码中我想使用后一种情况来处理错误。

为什么后一种情况不起作用?

您需要将Box强制转换为Box<dyn Shape> ,否则编译器不够聪明(仍然)来忽略类型:

fn get_shape_edges(name: &str) -> Result<u8, &str> {
    let shape: Box<dyn Shape> = match name {
        "triangle" => Ok(Box::new(Triangle {}) as Box<dyn Shape>),
        "rectanble" => Ok(Box::new(Rectangle {}) as Box<dyn Shape>),
        _ => Err("bad value")
    }?;
    Ok(shape.edges())
}

操场

顺便说一句,由于您已经在构建结果,因此您可以将edges映射到原始构建的边缘:

fn get_shape_edges(name: &str) -> Result<u8, &str> {
    let shape = match name {
        "triangle" => Ok(Box::new(Triangle {}) as Box<dyn Shape>),
        "rectanble" => Ok(Box::new(Rectangle {}) as Box<dyn Shape>),
        _ => Err("bad value")
    };
    shape.map(|s| s.edges())
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM