Подтвердить что ты не робот

Что делает что-то "признаком объекта"?

Недавние изменения ржавчины сделали более заметными для меня "объекты признаков", но у меня есть только туманное понимание того, что на самом деле делает что-то в объекте признаков. Одним из изменений, в частности, является предстоящее изменение, позволяющее объектам объектов пересылать реализации признаков во внутренний тип.

Учитывая черту Foo, я уверен, что Box<Foo> - объект-признак. Является ли &Foo также признаком объекта? Как насчет других умных указателей, таких как Rc или Arc? Как я могу сделать свой собственный тип, который будет считаться объектом объекта?

reference упоминает объекты объектов только один раз, но не что иное, как определение.

4b9b3361

Ответ 1

У вас есть объекты признаков, когда у вас есть указатель на признак. Box, Arc, Rc, а ссылка & - это, в основном, указатели. В терминах определения "объекта-объекта" они работают одинаково.

"Объекты-объекты" - это Rust, который принимает динамическую рассылку . Вот пример, который, я надеюсь, поможет показать, какие объекты признаков:

// define an example struct, make it printable
#[derive(Debug)]
struct Foo;

// an example trait
trait Bar {
    fn baz(&self);
}

// implement the trait for Foo
impl Bar for Foo {
    fn baz(&self) { println!("{:?}", self) }
}

// this is a generic function, that takes any T that implements trait Bar.
// It must resolve to a specific concrete T at compile time.
// The compiler creates a different version of this function
// for each concrete type used to call it so &T here is NOT
// a trait object (as T will represent a known, sized type
// after compilation)
fn static_dispatch<T>(t: &T) where T:Bar {
    t.baz(); // we can do this because t implements Bar
}

// this function takes a pointer to a something that implements trait Bar
// (it'll know what it is only at runtime). &Bar is a trait object.
// There only one version of this function at runtime, so this
// reduces the size of the compiled program if the function
// is called with several different types vs using static_dispatch.
// However performance is slightly lower, as the &Bar that 
// dynamic_dispatch receives is a pointer to the object +
// a vtable with all the Bar methods that the object implements.
// Calling baz() on t means having to look it up in this vtable.
fn dynamic_dispatch(t: &Bar) {
// --------------------^
// this is the trait object! It would also work with Box<Bar> or 
// Rc<Bar> or Arc<Bar>
//
    t.baz(); // we can do this because t implements Bar
}



fn main() {
    let foo = Foo;
    static_dispatch(&foo);
    dynamic_dispatch(&foo);
}

Для получения дополнительной справки существует хорошая глава "Объекты объектов" в книге Rust