snu*_*182 2 oop casting traits rust
试图重写一个特点偏色问题,描述在这里.坚持实现trait函数,该函数返回带有自己实现的枚举实例:
//the "trait matcher" enum
enum Side<'a> {
Good(&'a GoodDude),
Bad(&'a BadDude),
}
//very general trait
trait Dude {
fn who_am_i(&self) -> Side;
fn do_useful_stuff(&self);
}
//specific trait #1
trait GoodDude: Dude {
fn who_am_i_inner(&self) -> Side {
Side::Good(&self)
}
fn save_the_world(&self);
}
//specific trait #2
trait BadDude: Dude {
fn who_am_i_inner(&self) -> Side {
Side::Bad(&self)
}
fn do_evil(&self);
}
Run Code Online (Sandbox Code Playgroud)
但由于某些原因,这部分的编译因E0277而失败:
trait GoodDude: Dude {
fn who_am_i_inner(&self) -> Side {
Side::Good(&self) //&self should be &GoodDude, but compiler says it is not...
}
fn save_the_world(&self);
}
Run Code Online (Sandbox Code Playgroud)
并导致:
<anon>:16:20: 16:25 error: the trait `GoodDude` is not implemented for the type `&Self` [E0277]
<anon>:16 Side::Good(&self)
^~~~~
<anon>:16:20: 16:25 help: see the detailed explanation for E0277
<anon>:16:20: 16:25 note: required for the cast to the object type `GoodDude`
Run Code Online (Sandbox Code Playgroud)
这可以解决吗?
完整示例:https://play.rust-lang.org/?gist = 8ae2384e401da76c16214c4a642ce8b4&version=stable&backtrace=0
首先,self
in 的类型fn who_am_i_inner
已经是一个参考,所以你不需要&
.
fn who_am_i_inner(&self) -> Side {
Side::Good(self)
}
Run Code Online (Sandbox Code Playgroud)
然后,rustc抱怨......
<anon>:13:20: 13:24 error: the trait `core::marker::Sized` is not implemented for the type `Self` [E0277]
<anon>:13 Side::Good(self)
^~~~
<anon>:13:20: 13:24 help: see the detailed explanation for E0277
<anon>:13:20: 13:24 note: `Self` does not have a constant size known at compile-time
<anon>:13:20: 13:24 note: required for the cast to the object type `GoodDude`
Run Code Online (Sandbox Code Playgroud)
不可否认,错误信息非常不清楚,E0277是完全不同的.让我们尝试使用nightly编译器,它会提供更好的错误消息:
error: the trait bound `Self: std::marker::Sized` is not satisfied [--explain E0277]
--> <anon>:13:20
13 |> Side::Good(self)
|> ^^^^
help: consider adding a `where Self: std::marker::Sized` bound
note: required for the cast to the object type `GoodDude`
Run Code Online (Sandbox Code Playgroud)
好的,让我们尝试添加where Self: Sized
:
fn who_am_i_inner(&self) -> Side where Self: Sized {
Side::Good(self)
}
Run Code Online (Sandbox Code Playgroud)
现在它的工作原理.
世界得救.按任意键继续
5月4日和你一起
Pew Pew Pew
Luke我是你的父亲
该where Self: Sized
是除锈的方法,以表明该方法不能从特质对象使用.我们说如果你喜欢C++,那么方法会从"object-safety"中忽略,或者"不能是虚拟的".
结果是,如果你所有的都是luke: &GoodDude
,那么你就不能打电话,luke.who_am_i_inner()
因为它*luke
有一个未知的大小.
我们需要使该方法不是对象安全的原因是由于演员&Self ? &GoodDude
.在Rust中,trait对象引用就像&GoodDude
一个胖指针,在内部它表示为一个2元组(pointer, method_table)
.但是,在一个特征中,它self
是一个瘦指针.
我们无法将精简指针转换为胖指针,因为缺少信息method_table.如果我们知道具体类型,就可以填写.这就是为什么我们添加where Self: Sized
.
如果要使who_am_i_inner
对象安全,则无法提供默认实现.