此代码给出了编译错误:
trait IBoo {
fn new() -> Box<IBoo>;
}
虽然此代码编译时没有任何错误:
trait IBoo {
//fn new() -> Box<IBoo>;
}
trait IFoo {
fn new() -> Box<IBoo>;
}
rustc --explain E0038
没有直接暗示我为什么不可能。答案 0 :(得分:16)
编译器会告诉您完全这不起作用的原因:
>>> a = [1, 2, 3], [1, 4, 5], [1, 8, 9]
>>> [p for p in product(*a) if len(set(p)) == len(p)]
[(1, 4, 8), (1, 4, 9), (1, 5, 8), (1, 5, 9), (2, 1, 8), (2, 1, 9), (2, 4, 1), (2, 4, 8), (2, 4, 9), (2, 5, 1), (2, 5, 8), (2, 5, 9), (3, 1, 8), (3, 1, 9), (3, 4, 1), (3, 4, 8), (3, 4, 9), (3, 5, 1), (3, 5, 8), (3, 5, 9)]
注意最后一行。它告诉你错误的原因是error[E0038]: the trait `IBoo` cannot be made into an object
--> src/main.rs:2:5
|
2 | fn new() -> Box<IBoo>;
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `IBoo` cannot be made into an object
|
= note: method `new` has no receiver
不依赖于实现new()
特征的值的实例。
如果没有将某种指针指向 换句话说:因为你已经定义了一个无法动态调度的方法,所以 如果你想要某种构造函数,你需要有一些其他的写法。这可能是使用普通函数指针或IBoo
,则动态调度无法调用方法。如果无法通过动态调度调用它,则意味着它无法进入特征的关联vtable。 有是一个关联的vtable,因为这就像self
之类的工作。前段时间,核心Rust开发人员决定在特征中包含一个单“非对象安全”方法,使整体特征不被用作对象。 / p>
Box<IBoo>
trait 作为一个整体被取消了与动态调度一起使用的资格。< / p>
IBoo
特征,就像使用Java一样。
答案 1 :(得分:13)
方法没有接收器
从那时起,不能调用不带
self
参数的方法 它不会成为获取指向方法表的指针的方法。trait Foo { fn foo() -> u8; }
这可以称为
<Foo as Foo>::foo()
,这是不可能的 选择一个实现。添加绑定到这些方法的
Self: Sized
通常会产生这种情况 编译。trait Foo { fn foo() -> u8 where Self: Sized; }
你可以这样做:
trait IBoo {
fn new() -> Box<IBoo>
where
Self: Sized;
}
在其他情况下,您可以将限制放在整个impl:
上