[英]How do you implement specific types on generic traits in rust?
I initially assumed you could do this, because the documentation ( http://doc.rust-lang.org/rust.html#implementations ) suggests you can: 我最初假设您可以这样做,因为文档( 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;
}
}
...but that doesn't seem to work. ......但这似乎不起作用。 I get errors like:
我得到的错误如下:
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)
So I figured perhaps Foo has to be generic for this to work, so each specific Foo has it's own Bar implementation on it: 所以我想也许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();
}
...but my constructor seems to not work: ...但我的构造函数似乎不起作用:
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
Edit: I also tried: 编辑:我也尝试过:
impl<T> Foo<T> {
fn new<U>(value:f64) -> Foo<U> {
let rtn:Foo<U> = Foo { y: value };
return rtn;
}
}
Which solve the casting error, but results in: 哪个解决了转换错误,但结果是:
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);
^~~~~~~~~~~~~~~
O_o I have no idea what that means. O_o我不知道这意味着什么。
How do you do this? 你怎么做到这一点?
The impl Bar<int> for Foo
and impl Bar<uint> for Foo
is an error because, at the moment, only one impl
is allowed per trait, type pair (ignoring parameters on the trait). impl Bar<int> for Foo
的impl Bar<int> for Foo
impl Bar<uint> for Foo
是一个错误,因为目前每个trait只允许一个impl
,类型对(忽略trait上的参数)。 I went into more detail in this answer , including a work around using a secondary trait that avoids having to make Foo
generic (which is probably not what you want). 我在这个答案中详细介绍了 ,包括使用辅助特性的工作,避免了必须使
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) }
}
The second error is because you have two type parameters T
and U
"in scope" for the new
function, but are only specifying one ( U
). 第二个错误是因为
new
函数有两个类型参数T
和U
“in scope”,但只指定一个( U
)。 The T
needs to be specified by writing Foo::<int>::...
, however I don't think this is what you want, instead, you should be using the T
generic in the new
function: 需要通过编写
Foo::<int>::...
来指定T
,但是我不认为这是你想要的,相反,你应该在new
函数中使用T
generic:
impl<T> Foo<T> {
fn new(value: f64) -> Foo<T> { ... }
}
As background, the compiler needs to know the concrete type of T
because the implementation of new
could change: 作为背景,编译器需要知道
T
的具体类型,因为new
的实现可能会改变:
impl<T> Foo<T> {
fn new<U>(value:f64) -> Foo<U> {
Foo { y: value + std::mem::size_of::<T>() as f64 }
}
}
and then Foo::<()>::new::<int>(0.0)
would give y == 0.0
, but Foo::<u64>::new::<int>(0.0)
would give y == 8.0
. 然后
Foo::<()>::new::<int>(0.0)
会给出y == 0.0
,但是Foo::<u64>::new::<int>(0.0)
会给出y == 8.0
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.