了解特征和物体安全 [英] 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) {}
我收到
fn object_safety_dynamic(x: Trait) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `traits::Trait` cannot be made into an object
= note: the trait cannot require that `Self : Sized`
添加/更改:Sized
作为特征的继承或f
的绑定时,我会收到略有不同的错误消息.
When adding / changing :Sized
as the trait's inheritance or f
's bound I receive slightly different error messages.
有人可以解释:
-
为什么这个特定示例不起作用? 特质对象一章指出那么,什么使方法对象成为对象-safe?每个方法都必须要求
Self: Sized
".那不是实现吗?
Why does this particular example not work? The chapter Trait Objects states "So what makes a method object-safe? Each method must require that
Self: Sized
". Isn't that fulfilled?
Trait: Sized
和where Self: Sized
有什么区别? (嗯,是的,一个继承了特征,另一个继承了参数绑定,但是从Rust的特征对象的角度来看?
What is the difference between Trait: Sized
and where Self: Sized
? (Well, yes, one inherits the trait 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.
编辑-跟进:
解决固定尺寸的注释.
trait TraitB {
fn f(&self) -> i32 where Self: Sized;
fn g<T>(&self, t:T) -> i32 where Self: Sized;
}
推荐答案
为什么这个特定示例不起作用? 特性对象"一章指出:是什么使方法成为对象安全的?每个方法必须要求具有自身:大小".那不是实现吗?
Why does this particular example not work? The chapter Trait Objects states "So what makes a method object-safe? Each method must require that Self: Sized". Isn't that fulfilled?
这个问题确实是:什么是特质对象?
特质对象是面向对象范例中的接口:
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.
具体类型是未知的,但是,这意味着包含内存的存储区域的大小也是 ;因此,只能在 reference 或 pointer (例如&TraitObject
,&mut TraitObject
或Box<TraitObject>
)后面操纵特质对象.
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 &TraitObject
, &mut TraitObject
or Box<TraitObject>
for example.
在内存级别,它们的表示方式相同:
At the memory level, each of them is represented identically:
- 指向虚拟表的指针,这是一种结构,该结构在特征对象的每个方法"中以固定的偏移量保留一个函数指针,
- 指向对象实际数据的指针.
特质:大小"和自我:大小"之间有什么区别? (嗯,是的,一个继承了特征,另一个继承了参数绑定,但是从Rust的特征对象的角度来看?)
What is the difference between Trait: Sized and where Self: 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
指出,特征本身只能针对已实现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.
注意:实现特征时,所有方法都必须最终具有定义;否则,所有方法都必须具有定义.因此,只有在为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屋!