Generics 隐藏和接收通用T对象

Generics 隐藏和接收通用T对象,generics,rust,dynamic-dispatch,Generics,Rust,Dynamic Dispatch,给出了以下防锈代码: struct Wrapper<T> { data: Vec<T>, // more attributes... } trait DataWrapper<T> { fn get_column(&self) -> &Vec<T>; fn get_data(&self, row: usize) -> &T; } impl<T> DataWrapper

给出了以下防锈代码:

struct Wrapper<T> {
    data: Vec<T>, // more attributes...
}

trait DataWrapper<T> {
    fn get_column(&self) -> &Vec<T>;
    fn get_data(&self, row: usize) -> &T;
}

impl<T> DataWrapper<T> for Wrapper<T> {
    fn get_column(&self) -> &Vec<T> {
        &self.data
    }

    fn get_data(&self, row: usize) -> &T {
        &self.data[row]
    }
}

struct Inter<T> {
    inter_value: Wrapper<T>,
}

trait GetInter {
    fn get_count(&self) -> &str;
}

impl GetInter for Inter<i32> {
    fn get_count(&self) -> &str {
        "i32"
    }
}

impl GetInter for Inter<f64> {
    fn get_count(&self) -> &str {
        "f64"
    }
}

fn create_vector() -> Vec<Box<GetInter>> {
    // Add some sample data
    let x = Wrapper { data: vec![1, 2, 3] };
    let y = Wrapper { data: vec![1.1, 2.2, 3.3] };

    let mut vec: Vec<Box<GetInter>> = Vec::new();

    let m = Inter { inter_value: x };
    let m = Box::new(m);
    let m = m as Box<GetInter>;
    vec.push(m);

    let n = Inter { inter_value: y };
    let n = Box::new(n);
    let n = n as Box<GetInter>;
    vec.push(n);

    vec
}

struct ColumnWrapper {
    columns: Vec<Box<GetInter>>, // more attributes
}

fn create_column_wrapper() -> ColumnWrapper {
    let result = create_vector();

    ColumnWrapper { columns: result }
}

fn main() {
    let result = create_column_wrapper();

    for iter1 in result.columns {
        println!("1: {}", iter1.get_count());
    }
}
现在真正的问题开始了。我尝试访问存储在
包装器中的原始数据

我的第一个想法是使用Rust的动态调度功能。它应该在运行时检测真实的数据类型

已修改
main()
函数:

fn main() { 
    let result = create_column_wrapper();

    for iter1 in result.columns {
        println!("1: {}", iter1.get_count());

        for iter2 in dyn_dispatch(*iter1) {
            println!("2: {}", iter2);
        }
    }
}
相应且未测试的
dyn\u dispatch()
功能:

trait Foo<T> {
    fn method(x: &Inter<T>) -> &Vec<T>;
}

impl<i32> Foo<i32> for Inter<i32> {
    fn method(x: &Inter<i32>) -> &Vec<i32> {
        &x.inter_value.data
    }
}

impl<f64> Foo<f64> for Inter<f64> {
    fn method(x: &Inter<f64>) -> &Vec<f64> {
        &x.inter_value.data
    }
}

fn dyn_dispatch<T>(x: &GetInter) -> &Vec<T> {
    Foo::method(&x as &Inter<T>)
}
trait Foo{
fn方法(x:&Inter)->&Vec;
}
国际米兰的impl Foo{
fn方法(x:&Inter)->&Vec{
&x、 内部值数据
}
}
国际米兰的impl Foo{
fn方法(x:&Inter)->&Vec{
&x、 内部值数据
}
}
fn动态调度(x:&GetInter)->&Vec{
Foo::方法(&xas&Inter)
}
编译失败,并引发错误:

85:2错误:类型
Inter
的trait
Foo
实现冲突:[E0119]


你知道如何修复编译错误吗?还有一个更容易隐藏和访问泛型
T
对象的方法吗?

这里有几个问题

第一个错误:

错误:类型Inter的trait Foo实现冲突: [E0119]

实际上指的是:

impl<i32> Foo<i32> for Inter<i32> { ... }
impl<f64> Foo<f64> for Inter<f64> { ... }
也就是说,对任何T的
Inter
执行
Foo
,因此存在冲突的实现。解决方法是将它们写为:

impl Foo<i32> for Inter<i32> { ... }
impl Foo for Inter{…}

下一个问题是,您实际上并没有执行动态调度。您的
dyn\u dispatch
函数必须在编译时指定或推断
T
;它不能每次返回不同的类型;类似地,您不能像这样从
GetInter
向下转换到
Inter
。您需要以与之前相同的方式进行操作
GetInter::get_count

谢谢您的提示。将函数添加到
GetInter
以从
Wrapper
返回
inter\u值
,需要一个通用函数或特性。后者是不可能的。它将打破非通用数据的
ColumnWrapper
思想。只保留泛型函数。它必须如何实现,你能粘贴一个代码片段来解决这个问题吗?如果你隐藏在一个泛型特征后面(没有参数化),调用代码就不能使用实际的类型-编译时它不再可用。您可以实现一个
get_float()->选项
get_int()->选项
等,如果在不支持它的基础类型上调用该选项,则该选项将失败,但如果您有类似于
fn get()->t
,则每个实现者都必须使用任何类型。
impl Foo<i32> for Inter<i32> { ... }