了解特征和对象安全 [英] Understanding Traits and Object Safety
问题描述
我正在努力学习对象安全的基础知识.如果我有这个代码
I am struggling with the basics of object safety. If I have this code
struct S {
x: i32,
}
trait Trait: Sized {
fn f(&self) -> i32
where
Self: Sized;
}
fn object_safety_dynamic(x: Trait) {}
我收到
error[E0038]: the trait `Trait` cannot be made into an object
--> src/lib.rs:11:29
|
5 | trait Trait: Sized {
| ----- ----- ...because it requires `Self: Sized`
| |
| this trait cannot be made into an object...
...
11 | fn object_safety_dynamic(x: Trait) {}
| ^^^^^ the trait `Trait` cannot be made into an object
当我添加或删除 : Sized
作为 supertrait 或作为 f
的绑定时,我收到的错误消息略有不同.
When I add or remove : Sized
as the supertrait or as f
's bound, I receive slightly different error messages.
谁能解释一下:
为什么这个特定的例子不起作用?Trait Objects 一章指出:
那么是什么使方法对象安全呢?每个方法都必须要求 Self: Sized
So what makes a method object-safe? Each method must require that
Self: Sized
这还不够吗?
Trait: Sized
和 where Self: Sized
有什么区别?(嗯,是的,一个继承了 trait,另一个是参数绑定,但从 Rust 的 trait 对象的角度来看?
What is the difference between Trait: Sized
and where Self: Sized
? (Well, yes, one inherits the trait and the other one is a parameter bound, but from Rust's trait object perspective?
为了使 object_safety_dynamic
工作,我必须做出哪些首选更改?
What is the preferred change I had to make object_safety_dynamic
work?
如果重要的话,我正在使用 rustc 1.19.0-nightly (01951a61a 2017-05-20)
.
I am using rustc 1.19.0-nightly (01951a61a 2017-05-20)
if it matters.
解决关于固定尺寸的评论.
Addressing the comment on fixed sizes.
trait TraitB {
fn f(&self) -> i32
where
Self: Sized;
fn g<T>(&self, t: T) -> i32
where
Self: Sized;
}
推荐答案
为什么这个特定的例子不起作用?特征对象一章状态:
那么是什么使方法对象安全呢?每个方法都必须要求 Self: Sized
So what makes a method object-safe? Each method must require that
Self: Sized
这还不够吗?
这个问题实际上是:什么是特征对象?
trait 对象是面向对象范式中的一个接口:
A trait object is an interface in the Object-Oriented paradigm:
- 它公开了一组有限的方法,
- 应用于未知的具体类型.
应用操作的具体类型是未知的这一事实是人们使用特征对象的具体原因,因为它允许以统一的方式操作一组异构类型直到程序集级别.
The fact that the concrete type to which the operations is applied is unknown is specifically why one uses a trait object, as it allows manipulating a heterogeneous set of types in a uniform fashion down to the assembly level.
具体类型未知的事实意味着包含内存的内存区域的大小也未知;因此 trait 对象只能在 reference 或 pointer 之后进行操作,例如 &dyn TraitObject
、&mut dyn TraitObject
或 Box
例如.
The fact the concrete type is unknown, however, means that the size of the memory area which contains the memory is also unknown; therefore a trait object can only be manipulated behind a reference or pointer such as &dyn TraitObject
, &mut dyn TraitObject
or Box<dyn TraitObject>
for example.
在内存级别,它们中的每一个都表示相同:
At the memory level, each of them is represented identically:
- 一个指向虚拟表的指针,它是一种结构,每个方法"保存一个函数指针;特征对象的固定偏移量,
- 指向对象实际数据的指针.
Trait: Sized
和 where Self: Sized
有什么区别?(嗯,是的,一个继承了 trait,另一个是参数绑定,但从 Rust 的 trait 对象角度来看?)
What is the difference between
Trait: Sized
and whereSelf: Sized
? (Well, yes, one inherits the trait the other one is a parameter bound, but from Rust's trait object perspective?)
在 Rust 中没有继承.在两种情况下,它们都是边界:
There is no inheritance in Rust. In both cases those are bounds:
Trait: Sized
表明 trait 本身只能为已经实现了Sized
的类型实现,fn method(&self) where Self: Sized
声明只有实现了Sized
的类型才能实现这个方法.
Trait: Sized
states that the trait itself can only be implemented for a type that already implementsSized
,fn method(&self) where Self: Sized
states that only types that implementSized
can implement this method.
注意:在实现 trait 时,所有的方法都必须有一个定义;因此,后者只有在为具有 Self: Sized
绑定的方法提供默认实现时才真正有用,如 此处显示.
Note: when implementing a trait, all methods must end up having a definition; the latter is therefore only really useful if a default implementation is provided for the method with the Self: Sized
bound, as is shown here.
为了使 object_safety_dynamic
工作,我必须进行的首选更改是什么?
What is the preferred change I had to make
object_safety_dynamic
work?
你必须通过引用或指针来获取特征对象.使用引用还是指针取决于您是否要转让所有权.
You have to take the trait object by reference or pointer. Whether you use a reference or pointer depends on whether you want to transfer ownership or not.
这篇关于了解特征和对象安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!