57、impl Trait第二节

在参数位置的impl Trait

 

在前面的练习中,我们看到了如何使用impl Trait在不指定类型名的情况下返回类型。

相同的语法其实也可以用在参数的位置:

fn print_iter(iter: impl Iterator<Item = i32>) {
    for i in iter {
        println!("{}", i);
    }
}

print_iter以一个i32类型的迭代器作为参数,并打印每个元素。

在参数位置使用时,impl Trait等同于带有trait bound的泛型参数:

fn print_iter<T>(iter: T) 
where
    T: Iterator<Item = i32>
{
    for i in iter {
        println!("{}", i);
    }
}

 

缺点

 

根据经验,参数位置更适合用泛型而不是impl Trait

泛型允许调用者使用turbofish语法(::<>)明确指定参数的类型,这对消除歧义很有用。而impl Trait则不是这种情况。

 

练习

 

这一节的练习就是让我们使用impl Trait作为参数。

直接先看一下题目:

// TODO: Rework the signature of `TicketStore::add_ticket` to use a generic type parameter rather
//  than `impl Trait` syntax.
// TODO:重新设计 TicketStore::add_ticket 的签名,改用泛型类型参数,而不是 impl Trait 语法。

use ticket_fields::{TicketDescription, TicketTitle};

#[derive(Clone)]
pub struct TicketStore {
    tickets: Vec<Ticket>,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Ticket {
    pub title: TicketTitle,
    pub description: TicketDescription,
    pub status: Status,
}

#[derive(Clone, Debug, Copy, PartialEq)]
pub enum Status {
    ToDo,
    InProgress,
    Done,
}

impl TicketStore {
    pub fn new() -> Self {
        Self {
            tickets: Vec::new(),
        }
    }

    // Using `Into<Ticket>` as the type parameter for `ticket` allows the method to accept any type
    // that can be infallibly converted into a `Ticket`.
    // This can make it nicer to use the method, as it removes the syntax noise of `.into()`
    // from the calling site. It can worsen the quality of the compiler error messages, though.
    // 使用 Into<Ticket> 作为 ticket 的类型参数,允许该方法接受任何可以无错转换为 Ticket 的类型。
    // 这使得方法的使用更加便捷,因为它在调用位置消除了 .into() 的语法冗余。
    // 不过,这也可能降低编译器错误消息的质量。
    pub fn add_ticket/* TODO */ {
        self.tickets.push(ticket.into());
    }
}

 

我的答案:

pub fn add_ticket(&mut self,ticket:impl Into<Ticket>) {
    self.tickets.push(ticket.into());
}

但是发现不对,我看了一下作者的答案,感觉差不太多啊,为什么不对呢?

 

pub fn add_ticket<T: Into<Ticket>>(&mut self, ticket: T) {
	self.tickets.push(ticket.into());
}

然后我又看了一下题目,原来题目写明了,不让用impl Trait。那么这里为什么不能用impl Trait呢?看起来他们不都是一样的吗?

 

好吧,查了查资料,我明白了,就是我的写法问题,作者限制了不让用impl Trait,那就别用impl Trait。其实实际上,我那个写法问题并不是特别大。

 

这一节就先到这里了。

阅读剩余
THE END