是什么使某物成为“特质对象"? [英] What makes something a "trait object"?

查看:94
本文介绍了是什么使某物成为“特质对象"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近的Rust更改使特质对象"对我来说更加突出,但是我对将某物真正变成特质对象的东西只有模糊的了解.特别是其中一项更改是即将到来的更改,以允许特征对象转发特征实现到内部类型.

Recent Rust changes have made "trait objects" more prominent to me, but I only have a nebulous grasp of what actually makes something into a trait object. One change in particular is the upcoming change to allow trait objects to forward trait implementations to the inner type.

给出一个特征Foo,我很确定Box<Foo>/Box<dyn Foo>是一个特征对象. &Foo/&dyn Foo也是特征对象吗?像RcArc这样的其他智能指针呢?我该如何创建属于特征对象的自己的类型?

Given a trait Foo, I'm pretty sure that Box<Foo> / Box<dyn Foo> is a trait object. Is &Foo / &dyn Foo also a trait object? What about other smart-pointer things like Rc or Arc? How could I make my own type that would count as a trait object?

引用仅提及特征对象一次,但没有提及定义.

The reference only mentions trait objects once, but nothing like a definition.

推荐答案

当具有指向特征的指针时,就具有特征对象. BoxArcRc和引用&都是指针.在定义特征对象"方面,它们以相同的方式工作.

You have trait objects when you have a pointer to a trait. Box, Arc, Rc and the reference & are all, at their core, pointers. In terms of defining a "trait object" they work in the same way.

特质对象"是Rust在动态分配中的做法. 这是一个示例,我希望可以帮助说明什么特征对象:

"Trait objects" are Rust's take on dynamic dispatch. Here's an example that I hope helps show what trait objects are:

// 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). &dyn Bar is a trait object.
// There's 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 &dyn 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: &dyn Bar) {
    // ----------------^
    // this is the trait object! It would also work with Box<dyn Bar> or
    // Rc<dyn Bar> or Arc<dyn Bar>
    //
    t.baz(); // we can do this because t implements Bar
}

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

要进一步参考,请参阅特质对象"一章Rust书的内容

For further reference, there is a good Trait Objects chapter of the Rust book

这篇关于是什么使某物成为“特质对象"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆