Understanding Traits and Object Safety

前端 未结 2 1470
攒了一身酷
攒了一身酷 2020-11-29 12:19

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:         


        
2条回答
  •  臣服心动
    2020-11-29 13:08

    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?

    This question really is: What is a Trait Object?

    A Trait Object is an interface in the Object-Oriented paradigm:

    • it exposes a limited set of methods,
    • which are applied to an unknown concrete type.

    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.

    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 for example.

    At the memory level, each of them is represented identically:

    • a pointer to a virtual table, which is a structure holding one function pointer per "method" of the trait object at a fixed offset,
    • a pointer to the actual data of the object.

    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?)

    There is no inheritance in Rust. In both cases those are bounds:

    • Trait: Sized states that the trait itself can only be implemented for a type that already implements Sized,
    • fn method(&self) where Self: Sized states that only types that implement Sized can implement this method.

    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.

    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.

提交回复
热议问题