为 trait 实现 trait 时不能将 `AsArray` 做成对象
`AsArray` cannot be made into an object when implementing a trait for a trait
基本上我正在尝试制作一个特征,表明能够转换为 2D ndarray
又名 ndarray::Array2
:
trait Into2DArray{
fn to_array(&self) -> Array2<f64>;
}
出于某些深奥的原因,我想通过扩展现有的 AsArray
trait, but Rust forbids me from implementing a third party trait for a third party struct (polars::DataFrame
) 来做到这一点,所以我必须为此制定自己的特征。
无论如何,这很适合 polars::DataFrame
:
impl Into2DArray for DataFrame {
fn to_array(&self) -> Array2<f64> {
return self.to_array();
}
}
但是,我也想为任何已经转换为二维数组的东西实现这个,所以我为上面提到的 AsArray
特性实现了这个特性:
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>
我知道这与 object safety 有关,但我认为我已经满足该页面上提到的所有条件,即特征不 return Self
,并且AsArray
的所有通用参数都已指定。
出了什么问题,我该如何解决?
您试图做的是为 AsArray
动态特征对象实现 Into2DArray
特征。无论如何,应该有使用 AsArray
而不使用 dyn
的警告。
但这不是你真正想要的。您想要为实现 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.
}
基本上我正在尝试制作一个特征,表明能够转换为 2D ndarray
又名 ndarray::Array2
:
trait Into2DArray{
fn to_array(&self) -> Array2<f64>;
}
出于某些深奥的原因,我想通过扩展现有的 AsArray
trait, but Rust forbids me from implementing a third party trait for a third party struct (polars::DataFrame
) 来做到这一点,所以我必须为此制定自己的特征。
无论如何,这很适合 polars::DataFrame
:
impl Into2DArray for DataFrame {
fn to_array(&self) -> Array2<f64> {
return self.to_array();
}
}
但是,我也想为任何已经转换为二维数组的东西实现这个,所以我为上面提到的 AsArray
特性实现了这个特性:
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>
我知道这与 object safety 有关,但我认为我已经满足该页面上提到的所有条件,即特征不 return Self
,并且AsArray
的所有通用参数都已指定。
出了什么问题,我该如何解决?
您试图做的是为 AsArray
动态特征对象实现 Into2DArray
特征。无论如何,应该有使用 AsArray
而不使用 dyn
的警告。
但这不是你真正想要的。您想要为实现 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.
}