Rust 为什么一种特质不能自我建构?
这段代码给了我一个编译错误:Rust 为什么一种特质不能自我建构?,rust,Rust,这段代码给了我一个编译错误: trait IBoo { fn new() -> Box<IBoo>; } trait IBoo{ fn new()->Box; } 虽然此代码编译时没有任何错误: trait IBoo { //fn new() -> Box<IBoo>; } trait IFoo { fn new() -> Box<IBoo>; } trait IBoo{ //fn new()->Box; }
trait IBoo {
fn new() -> Box<IBoo>;
}
trait IBoo{
fn new()->Box;
}
虽然此代码编译时没有任何错误:
trait IBoo {
//fn new() -> Box<IBoo>;
}
trait IFoo {
fn new() -> Box<IBoo>;
}
trait IBoo{
//fn new()->Box;
}
特征IFoo{
fn new()->Box;
}
rustc--explain E0038
并没有给我一个为什么不可能的直接提示编译器会告诉您这不起作用的确切原因:
error[E0038]:无法将特征'IBoo'生成对象
-->src/main.rs:2:5
|
2 | fn new()->框;
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^无法将特征“IBoo”制成
|
=注意:方法“new”没有接收器
注意最后一行。它告诉您错误的原因是new()
不依赖于具有实现IBoo
特征的值的实例
通过不使用某种指向self
的指针,动态分派无法调用该方法。如果它不能被动态分派调用,这意味着它不能进入trait的相关vtable。必须有一个相关的vtable,因为类似于Box
的东西就是这样工作的。不久前,core Rust开发人员决定在一个特性中包含一个“非对象安全”方法,从而取消了将整个特性用作对象的资格
换言之:因为您定义了一个不能动态调度的方法,IBoo
trait作为一个整体被取消了与动态调度一起使用的资格
如果你想要某种构造函数,你需要有其他的编写方法。这可以使用普通函数指针,也可以使用IBooFactory特性,就像Java一样。这来自:
方法没有接收器
无法调用不带self
参数的方法,因为
没有办法为它们获取指向方法表的指针
trait Foo {
fn foo() -> u8;
}
这可以称为::foo()
,它将无法
选择一个实现
添加绑定到这些方法的Self:Sized
通常会使
编译
trait Foo {
fn foo() -> u8 where Self: Sized;
}
您可以这样做:
trait IBoo {
fn new() -> Box<IBoo>
where
Self: Sized;
}
trait IBoo{
fn new()->Box
哪里
自我:大小;
}
在其他情况下,您可以对整个impl设置限制:谢谢您的回答,但是为什么编译器的错误只在使用
IFoo
或IBoo
时发出?为什么我可以定义trait
,而函数没有self
,并且只有在我尝试使用这种trait时才会发出错误?@user1244932因为trait不仅仅用于动态调度。静态调度没有问题。编译器不必构造vtable,除非您要求它构造vtable,而这正是它抱怨的地方。再次感谢您的回答aSpex的回答会使这个无效吗?看来,trait IBoo{fn new()->Self:Sized;}
编译得很好。(不过,我还没有试着实际调用new
)好的,我想我现在明白了。您的答案中的一句话“因为您定义了一个不能动态调度的方法,所以IBoo特性作为一个整体不适合用于动态调度”仍然有效。aSpex解决方案的作用是显式地使trait对象无法使用new()
,从而使它(可以说)成为可选的。当非特质对象安全new
不再存在时,该特质再次适合与特质对象类型(如Box
)一起使用。谢谢!我没有意识到在个体特质方法中添加Self
约束是可能的。我原以为约束必须在特质本身,而这类问题只能通过打破特质来解决;我完全忘记了。更多关于Self:Sized
,开始!