Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 为什么一种特质不能自我建构?_Rust - Fatal编程技术网

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
    并没有给我一个为什么不可能的直接提示
  • 是否可以在一个接口(trait)中结合构造和方法

  • 编译器会告诉您这不起作用的确切原因:

    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
    ,开始!