我最初认为您可以这样做,因为文档(http://doc.rust-lang.org/rust.html#implementations)建议您可以:

trait Bar<T> {
  fn ex(&self) -> T;
}

struct Foo {
  y:f64
}

impl Bar<int> for Foo {
  fn ex(&self) -> int {
    return self.y.floor() as int;
  }
}

impl Bar<uint> for Foo {
  fn ex(&self) -> uint {
    if (self.y < 0.0) {
      return 0u;
    }
    return self.y.floor() as uint;
  }
}

...但这似乎不起作用.我会遇到如下错误:

error: multiple applicable methods in scope
error: expected Bar<uint>, but found Bar<int> (expected uint but found int)
error: expected Bar<int>, but found Bar<uint> (expected int but found uint)

所以我想也许Foo必须是通用的,这样才能工作,所以每个特定的Foo都有自己的Bar实现:

trait Bar<T> {
  fn ex(&self) -> T;
}

struct Foo<T> {
  y:f64
}

impl<T> Foo<T> {
  fn new<U>(value:f64) -> Foo<U> {
    return Foo { y: value } as Foo<U>;
  }
}

impl Bar<int> for Foo<int> {
  fn ex(&self) -> int {
    return self.y.floor() as int;
  }
}

impl Bar<uint> for Foo<uint> {
  fn ex(&self) -> uint {
    if (self.y < 0.0) {
      return 0u;
    }
    return self.y.floor() as uint;
  }
}

fn main() {
  let z = Foo::new::<int>(100.5);
  let q = Foo::new::<uint>(101.5);
  let i:int = z.ex();
  let j:uint = q.ex();
}

...但我的构造函数似乎不起作用:

x.rs:11:12: 11:38 error: non-scalar cast: `Foo<<generic #1>>` as `Foo<U>`
x.rs:11     return Foo { y: value } as Foo<U>;
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

编辑:我也试过:

impl<T> Foo<T> {
  fn new<U>(value:f64) -> Foo<U> {
    let rtn:Foo<U> = Foo { y: value };
    return rtn;
  }
}

解决了铸造误差,但导致:

x.rs:32:11: 32:26 error: cannot determine a type for this expression: unconstrained type
x.rs:32   let z = Foo::new::<int>(100.5);
                  ^~~~~~~~~~~~~~~

我不知道那是什么意思.

你是怎么做到的?

推荐答案

impl Bar<int> for Fooimpl Bar<uint> for Foo是一个错误,因为目前每个特征类型对只允许有一个impl(忽略特征上的参数).I went into more detail in this answer,包括一个使用次要特征的变通方法,它可以避免让Foo成为泛型(这可能不是你想要的).

trait BarForFoo {
    fn do_ex(foo: &Foo) -> Self;
}
impl BarForFoo for int {
    fn do_ex(foo: &Foo) -> int {
        foo.y.floor() as int
    }
}    
impl BarForFoo for uint {
    fn do_ex(foo: &Foo) -> uint {
        foo.y.max(0.0).floor() as uint
    }
}

impl<T: BarForFoo> Bar<T> for Foo {
    fn ex(&self) -> T { BarForFoo::do_ex(self) }
}

第二个错误是因为new函数有两个类型参数TU"在范围内",但只指定了一个(U).T需要通过写Foo::<int>::...来指定,但是我不认为这是你想要的,相反,你应该在new函数中使用T泛型:

impl<T> Foo<T> {
    fn new(value: f64) -> Foo<T> { ... }
}

作为背景,编译器需要知道T的具体类型,因为new的实现可能会发生变化:

impl<T> Foo<T> {
  fn new<U>(value:f64) -> Foo<U> {
    Foo { y: value + std::mem::size_of::<T>() as f64 }
  }
}

然后Foo::<()>::new::<int>(0.0)会得到y == 0.0,但Foo::<u64>::new::<int>(0.0)会得到y == 8.0.

Rust相关问答推荐

如何格式化传入Rust中mysql crate的Pool::new的字符串

支持TLS的模拟HTTP服务器

如何用Axum/Tower压缩Html内容?

不能在Rust中使用OpenGL绘制三角形

在Rust中声明和定义一个 struct 体有什么区别

Rust将String上的迭代器转换为&;[&;str]

解析程序无法在Cargo 发布中 Select 依赖版本

返回Result<;(),框<;dyn错误>>;工作

随机函数不返回随机值

在 Rust 中,在第一个空格上分割字符串一次

如何限制 GtkColumnView 行数

为什么需要静态生命周期以及在处理 Rust 迭代器时如何缩小它?

在没有任何同步的情况下以非原子方式更新由宽松原子操作 Select 的值是否安全?

Rust 1.70 中未找到 Trait 实现

`tokio::pin` 如何改变变量的类型?

pyO3 和 Panics

具有在宏扩展中指定的生命周期的枚举变体数据类型

在每个循环迭代中删除borrow

判断对象是 PyDatetime 还是 Pydate 的实例?

如何从 many0 传播 Nom 失败上下文?