< 返回版块

ChariotChai 发表于 2019-06-12 12:40

Tags:trait对象, 泛型

  • S1S2分别实现了ATrait特性
trait ATrait {}

struct S1 {}

impl ATrait for S1 {}

struct S2 {}

impl ATrait for S2 {}
  • 以下代码是能够编译通过的,返回一个Result
fn foo1(i: i32) -> Result<Box<ATrait>, ()> {
    if i < 0 {
        Ok(Box::new(S1 {}))
    } else {
        Ok(Box::new(S2 {}))
    }
}
  • 但是以下代码就无法编译通过(实际上就是上面的foo1方法的返回值通过另一个函数返回)
fn f1() -> Result<Box<S1>, ()> {
    Ok(Box::new(S1 {}))
}

fn f2() -> Result<Box<S2>, ()> {
    Ok(Box::new(S2 {}))
}
fn foo2(i: i32) -> Result<Box<ATrait>, ()> {
    if i < 0 {
        f1()
    } else {
        f2()
    }
}
  • 报错内容如下,是因为f1返回值的类型与foo2不匹配导致
46 | fn foo2(i: i32) -> Result<Box<ATrait>, ()> {
   |                    ----------------------- expected `std::result::Result<std::boxed::Box<(dyn ATrait + 'static)>, ()>` because of return type
47 |     if i < 0 {
48 |         f1()
   |         ^^^^ expected trait ATrait, found struct `S1`
   |
   = note: expected type `std::result::Result<std::boxed::Box<(dyn ATrait + 'static)>, _>`
              found type `std::result::Result<std::boxed::Box<S1>, _>`
  • 但是如果返回的不是Result,而是ATrait对象指针,则编译是能通过的
fn foo3(i: i32) -> Box<ATrait> {
    if i < 0 {
        f1().unwrap()
    } else {
        f2().unwrap()
    }
}

问题

  • 为什么foo3(返回Box的函数)就不存在类型不匹配的问题?
  • 这种情况,有没有比较好的实现方式?(不需要在foo2方法中把f1f2函数返回的结果转换的那种)还是说只能在foo2中把f1f2Result拆开再重新包装?

丢给我几个链接或者关键词也可以的,感谢社区各位大佬!

评论区

写评论
作者 ChariotChai 2019-06-12 14:03

原来是因为Result没有隐式转换机制,谢谢! 对以下内容的回复:

laizy 2019-06-12 13:20

Box<S1>Box<dyn ATrait>的转换可以是隐式的。 但是Result和普通的Enum和Struct是一样的,类型之间没有这种转换,只能显式做

f1().map(|x|x as _)
1 共 2 条评论, 1 页