19、Traits(“接口”)
Traits
重新看之前的Ticket结构体
pub struct Ticket {
title: String,
description: String,
status: String,
}
之前我们所有的assertions(测试)都使用的是Ticket的字段。
assert_eq!(ticket.title(), "A new title");
如果我们想要直接比较两个Ticket实例呢?
let ticket1 = Ticket::new(/* ... */);
let ticket2 = Ticket::new(/* ... */);
ticket1 == ticket2
编译器会阻止我们:
error[E0369]: binary operation `==` cannot be applied to type `Ticket`
--> src/main.rs:18:13
|
18 | ticket1 == ticket2
| ------- ^^ ------- Ticket
| |
| Ticket
|
note: an implementation of `PartialEq` might be missing for `Ticket`
Ticket是一个新类型,它没有什么附加的行为。
Rust 不会因为两个 Ticket 实例包含字符串,就神奇地推断出如何比较它们。
不过,Rust 编译器正在朝着正确的方向引导我们:它提示我们可能缺少 PartialEq 的实现。
PartialEq是一个trait!
什么是traits
traits是Rust定义interfaces(接口)的方式。
traits定义了一组方法,类型必须实现这些方法,才算符合trait的规范。
定义一个trait
定义trait的语法是这样的:
trait <TraitName>{
fn <method_name>(<parameters>)-><return_type>;
}
比如,我们可以定义一个名为MaybeZero的trait,该trait要求它的实现者定义一个is_zero方法:
trait MaybeZero {
fn is_zero(self) -> bool;
}
实现一个trait
我们使用impl关键字去实现一个trait,和处理常规的方法有些类似,但是有些不同,以下是实现trait的语法:
impl <TraitName> for <TypeName> {
fn <method_name>(<parameters>) -> <return_type> {
// Method body
}
}
比如给自定义数字类型WarppingU32实现MaybeZerotrait:
pub struct WrappingU32 {
inner: u32,
}
impl MaybeZero for WrappingU32 {
fn is_zero(self) -> bool {
self.inner == 0
}
}
调用trait方法
使用.操作符即可调用trait方法,就像我们调用常规方法那样:
let x = WrappingU32 { inner: 5 };
assert!(!x.is_zero());
要想成功调用trait方法,必须确保两件事情:
- 类型必须实现trait
- trait必须在作用域内
为了满足后者,我们可以使用use crate::MaybeZero把想要使用的trait导入进来,以成功调用trait方法。
以下两种情况,不需要使用use把trait导入进来:
- trait的调用者与trait本身在同一个模块里
- trait定义在标准库的
prelude(引子,序幕)中,prelude是可以自动导入到所有Rust程序里面的一组trait和types的集合。就好比是在每一个Rust模块的开头都添加了std::prelude::*。
练习
既然学了trait的定义和调用,那么练习肯定就是这个了,这次的练习让我们实现一个trait,trait里面有一个方法
// Define a trait named `IsEven` that has a method `is_even` that returns a `true` if `self` is
// even, otherwise `false`.
//
// Then implement the trait for `u32` and `i32`.
也挺简单的,我一开始的代码是这样:
trait IsEven{
fn is_even(&self) -> bool;
}
impl IsEven for u32{
fn is_even(&self) -> bool{
if self%2==0{
true
}
else{
false
}
}
}
impl IsEven for i32{
fn is_even(&self) -> bool{
if self%2==0{
true
}
else{
false
}
}
}
结果check的时候,怎么也不行,报错提示,找不到is_even这个方法。
我寻思应该是要加上pub吧,试了给方法加,不行(
后来发现原来是要给trait的定义块加pub
pub trait IsEven{
fn is_even(&self) -> bool;
}
www,哈基C,难道你连这个都debug不出来吗(
好了,这一节的学习就先到这里了
