1

基本上我正在尝试制作一个表明能够转换为 2D ndarrayaka的特征ndarray::Array2

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

我想通过扩展现有AsArray特征来做到这一点,但是出于某种深奥的原因,Rust 禁止我为第三方 struct () 实现第三方特征polars::DataFrame,因此我必须为此创建自己的特征。

无论如何,这适用于polars::DataFrame

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

但是,我也想为任何已经可以转换为二维数组的东西实现这个,所以我为AsArray上面提到的 trait 实现了这个 trait:

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

然而,编译器让我为此感到悲痛:

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

我知道这与对象安全有关,但我认为我已经满足了该页面上提到的所有标准,即 trait doesn't return Self,并且AsArray指定了所有通用参数。

出了什么问题,我该如何解决?

4

1 回答 1

2

您尝试做的是Into2DArrayAsArray动态特征对象实现特征。无论如何都应该有使用警告AsArraydyn

但这不是你真正想要的。你想为任何实现它的类型实现它AsArray。就像你在评论中所做的那样。

了解这两件事之间的区别很重要:

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.
}
于 2021-07-22T23:24:40.593 回答