简体   繁体   English

为 trait 实现 trait 时,不能将 `AsArray` 变成对象

[英]`AsArray` cannot be made into an object when implementing a trait for a trait

Basically I'm trying to make a trait that indicates the ability to be converted into a 2D ndarray aka ndarray::Array2 :基本上,我正在尝试制作一个特征,表明能够转换为 2D ndarray aka ndarray::Array2

trait Into2DArray{
    fn to_array(&self) -> Array2<f64>;
}

I would like to do this by expanding the existingAsArray trait, but Rust forbids me from implementing a third party trait for a third party struct ( polars::DataFrame ) for some esoteric reason, so instead I have to make my own trait for this.我想通过扩展现有的AsArray特征来做到这一点,但 Rust 禁止我为第三方结构( polars::DataFrame )实现第三方特征,因为某些深奥的原因,所以我必须为此创建自己的特征.

Anyway, this works well for polars::DataFrame :无论如何,这适用于polars::DataFrame

impl Into2DArray for DataFrame {
    fn to_array(&self) -> Array2<f64> {
        return self.to_array();
    }
}

However, I also want to implement this for anything that is already convertable into a 2D array, so I implement this trait for the AsArray trait mentioned above:但是,我也想为任何已经可以转换为二维数组的东西实现这个,所以我为上面提到的AsArray特性实现了这个特性:

impl Into2DArray for AsArray<'_, f64, Ix2> {
    fn to_array(&self) -> Array2<f64> {
        return self.into();
    }
}

However the compiler gives me grief for this:然而,编译器让我为此感到悲伤:

   |
26 | impl Into2DArray for AsArray<'_, f64, Ix2> {
   |                      ^^^^^^^^^^^^^^^^^^^^^ `AsArray` cannot be made into an object
   |
   = note: the trait cannot be made into an object because it requires `Self: Sized`
   = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

I understand that has something to do with object safety but I thought I had fulfilled all the criteria mentioned on that page, namely the trait doesn't return Self , and all the generic parameters of AsArray are specified.我知道这与对象安全有关,但我认为我已经满足了该页面上提到的所有标准,即 trait 不返回Self ,并且指定了AsArray所有通用参数。

What is going wrong, and how can I fix it?出了什么问题,我该如何解决?

What you were trying to do is implementing the Into2DArray trait for the AsArray dynamic trait object.您尝试做的是为AsArray动态特征对象实现Into2DArray特征。 There should have been a warning of using AsArray without dyn anyway.无论如何,应该有一个警告, AsArray没有dyn情况下使用AsArray

But this is not what you actually want.但这并不是你真正想要的。 You want to implement it for any type that implements AsArray .您想为任何实现AsArray类型实现AsArray Just like you did in your comment.就像你在评论中所做的那样。

It is important to know the difference between these two things:了解这两件事之间的区别很重要:

trait NeedThis {
    fn can_be_called_by_the_impl(&self) {}
}

trait ToDoThis {
    fn example(&self);
}

impl ToDoThis for dyn NeedThis {
    fn example(&self) {
        self.can_be_called_by_the_impl()
    }
}

impl NeedThis for u8 {}

fn main() {
    let num: u8 = 0;
    // num.example(); // doesn't work because ToDoThis is not implemented for u8

    let num_as_trait_obj: &dyn NeedThis = &0_u8 as &dyn NeedThis;
    num_as_trait_obj.example(); // works because this time it is a trait object
}
trait NeedThis {
    fn can_be_called_by_the_impl(&self) {}
}

trait ToDoThis {
    fn example(&self);
}

// removing ?Sized would make it the same as T: NeedThis + Sized
impl<T: NeedThis + ?Sized> ToDoThis for T {
    fn example(&self) {
        self.can_be_called_by_the_impl()
    }
}

impl NeedThis for u8 {}

fn main() {
    let num: u8 = 0_u8;
    num.example(); // works because we implemented it for all types that implement NeedThis

    let num_as_trait_obj: &dyn NeedThis = &0_u8 as &dyn NeedThis;
    num_as_trait_obj.example(); // works because dyn NeedThis also implements NeedThis.
    // This is only true because we added ?Sized to the bounds of the impl block.
    // Otherwise it doesn't work because dyn NeedThis is not actually Sized.
    // And a Sized bound is implied by default.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM