简体   繁体   English

从实施到实施

[英]implementing from and into

I want to transform types of "A" into "B" and collections of "A" to collections of "B" (and vice versa).我想将“A”的类型转换为“B”,将“A”的 collections 转换为“B”的 collections(反之亦然)。

I have some misunderstanding of how the mechanism works.我对该机制的工作原理有一些误解。

I assumed implementing From on the base type would transfer to collections similarly without explicitly implementing.我假设在基本类型上实现From将类似地转移到 collections 而无需显式实现。

For example:例如:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=aaffccd542d750a4e7061fc0045b712c 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
}

the error I get for converting the collections:我在转换 collections 时遇到的错误:

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

Is there a "blanket" implementation for these nested conversions?这些嵌套转换是否有“一揽子”实现? If not what is the best way to achieve this flexibility?如果不是,实现这种灵活性的最佳方式是什么?

Consume the vec with into_iter and map Into::into before collecting the items into a new vector:在将项目收集到新向量之前,使用into_iter和 map Into::into使用 vec:

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

Playground 操场

If you are looking for a similar syntax to the one provided by From::from and Into::into , you may want to consider writing your own generic trait, FromVec , eg:如果您正在寻找与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()  
   }
}

along with its corresponding buddy trait, IntoVec :连同其相应的伙伴特征IntoVec

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

and providing it with a blanket implementation:并为其提供一揽子实施:

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

This way, you will be calling from_vec() and into_vec() in a similar way as you would call from() and into() :这样,您将以与调用from() () 和 into() 类似的方式调用from_vec()into_vec() 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();
}

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

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