【问题标题】:implementing from and into从实施到实施
【发布时间】:2021-06-01 09:38:47
【问题描述】:

我想将“A”的类型转换为“B”,将“A”的集合转换为“B”的集合(反之亦然)。

我对机制的工作原理有些误解。

我假设在基本类型上实现 From 会以类似方式转移到集合,而无需显式实现。

例如:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=aaffccd542d750a4e7061fc0045b712c

struct A {
    text: String
}

struct B {
    text: String
}

impl From<A> for B {
    fn from(a: A) -> Self {
        B { text: a.text } 
    }
}
fn main() {
    let a = A { text: "hello".to_string() };
    let b = B::from(a); // works
    let a2 = A { text: "hello".to_string() };
    let b2 = a.into(); // works
    let v1 = vec![A { text: "hello".to_string()}];
    let v2 = Vec::<B>::from(v1); // doesn't work
    let v2 : Vec<B> = v1.into(); // doesn't work
}

我在转换集合时遇到的错误:

Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Vec<B>: From<Vec<A>>` is not satisfied
  --> src/main.rs:20:14
   |
20 |     let v2 = Vec::<B>::from(v1); // doesn't work
   |              ^^^^^^^^^^^^^^ the trait `From<Vec<A>>` is not implemented for `Vec<B>`
   |
   = help: the following implementations were found:
             <Vec<T, A> as From<Box<[T], A>>>
             <Vec<T> as From<&[T]>>
             <Vec<T> as From<&mut [T]>>
             <Vec<T> as From<BinaryHeap<T>>>
           and 6 others
   = note: required by `from`

error[E0277]: the trait bound `Vec<B>: From<Vec<A>>` is not satisfied
  --> src/main.rs:21:26
   |
21 |     let v2 : Vec<B> = v1.into(); // doesn't work
   |                          ^^^^ the trait `From<Vec<A>>` is not implemented for `Vec<B>`
   |
   = help: the following implementations were found:
             <Vec<T, A> as From<Box<[T], A>>>
             <Vec<T> as From<&[T]>>
             <Vec<T> as From<&mut [T]>>
             <Vec<T> as From<BinaryHeap<T>>>
           and 6 others
   = note: required because of the requirements on the impl of `Into<Vec<B>>` for `Vec<A>`

这些嵌套转换是否有“一揽子”实现?如果不是,实现这种灵活性的最佳方式是什么?

【问题讨论】:

    标签: generics rust traits


    【解决方案1】:

    使用 into_iter 和映射 Into::into 的 vec,然后将项目收集到新向量中:

    let v2: Vec<B> = v1.into_iter().map(Into::into).collect();
    

    Playground

    【讨论】:

      【解决方案2】:

      如果您正在寻找与From::fromInto::into 提供的语法相似的语法,您可能需要考虑编写自己的通用特征FromVec,例如:

      trait FromVec<T> {
         fn from_vec(val: Vec<T>) -> Self;
      }
      
      impl<T, S: From<T>> FromVec<T> for Vec<S> {
         fn from_vec(val: Vec<T>) -> Self {
            val.into_iter().map(Into::into).collect()  
         }
      }
      

      连同其对应的好友特质,IntoVec

      trait IntoVec<T> {
         fn into_vec(self) -> Vec<T>;
      }
      

      并为其提供一揽子实现:

      impl<T, S> IntoVec<T> for Vec<S>
         where Vec<T>: FromVec<S>
      {
         fn into_vec(self) -> Vec<T> {
            Vec::from_vec(self)
         }
      }
      

      这样,您调用from_vec()into_vec() 的方式与调用from()into() 的方式类似:

      fn main() {
          let vec_a = vec![A { text: "hello".to_string() } ];
          let vec_b = Vec::<B>::from_vec(vec_a);
      
          let vec_a = vec![A { text: "hello".to_string() } ];
          let vec_b: Vec<B> = vec_a.into_vec();
      }
      

      【讨论】:

      • 为什么这部分不是标准库:)?
      猜你喜欢
      • 2019-12-16
      • 2022-07-16
      • 2011-05-04
      • 2010-10-03
      • 2015-10-03
      • 2019-12-19
      • 2010-10-17
      • 2014-06-05
      • 2021-09-20
      相关资源
      最近更新 更多