我有一个特征 Vertex
,我想要几个结构来实现。我想要求一个实现 trait 的结构有一个返回该结构的 Vector 的方法。所以实现看起来像这样。
struct Point {
// ...
}
impl Vertex for Point {
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self> {
unimplemented!()
}
}
这样你就可以像Point::from_byte_buffer(...)
一样称呼它。但是,我不知道如何在特征中编写方法签名。这是我最好的猜测。
trait Vertex {
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self>;
}
然而,这给了我一个错误,
the size for values of type `Self` cannot be known at compilation time
这有点意思,因为在这种情况下 Self 不是一个具体的类型。我想过做这样的事情,
trait Vertex {
fn from_byte_buffer<V: Vertex>(buffer: &[u8]) -> Vec<V>;
}
但这与实现特征的具体类型无关。我需要使用关联类型吗?
答案 0 :(得分:2)
所有 Rust trait 都有一个隐含的 ?Sized
界限,所以:
trait Trait {}
脱糖:
trait Trait where Self: ?Sized {}
这是默认完成的,因此可以将 trait 转换为 trait 对象。您可以通过在特征上设置显式 Sized
绑定来覆盖此默认值,例如
trait Trait: Sized {}
或者可选地在特定特征项上设置显式 Sized
绑定,例如
trait Trait {
fn func() where Self: Sized {}
}
后一种方法的好处是您仍然可以将上述特征转换为特征对象(尽管您将无法调用该特定的 Sized
方法)。
将第一个解决方案应用于您的示例会产生:
trait Vertex: Sized {
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self>;
}
struct Point;
impl Vertex for Point {
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self> {
todo!()
}
}
应用第二种解决方案产生:
trait Vertex {
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self> where Self: Sized;
}
struct Point;
impl Vertex for Point {
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self> {
todo!()
}
}
两者都按照您的预期进行编译和工作。首先需要将 Self
标记为 Sized
的原因是因为 Vec
只能包含编译时已知大小的项目。
如果您想更彻底和深入地了解 Rust 中大小的工作原理,我建议您阅读 Sizedness in Rust(免责声明:我写的)。
答案 1 :(得分:0)
您可以将 Self
绑定为 Sized
:
trait Vertex where Self: Sized {
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self>;
}
或者干脆
trait Vertex: Sized {
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self>;
}
因为 Self
是 Vertex
。
编辑:或使用关联类型:
trait Vertex
where
<Self as Vertex>::Inner: Sized
{
type Inner;
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self::Inner>;
}
struct Point {
}
impl Vertex for Point {
type Inner = Point;
fn from_byte_buffer(buffer: &[u8]) -> Vec<Self::Inner> {
vec![]
}
}