Appearance
5.9 supertrait
有时候,我们可能需要在一个 trait 中使用另一个 trait 的功能。这时候将依赖所使用的 trait 也需要被实现。
这个所依赖的 trait 被称为我们所定义的 trait 的 supertrait(超级 trait)。 一个 trait 可以有一个或者多个 supertraits,它们可以被用来约束实现了子 trait 的类型。
示例:
rust
use std::fmt::{Debug, Display};
trait Foo: Debug + Display {
// trait 方法定义
}
在这个例子中,通过使用+
运算符来同时指定多个超级 trait,可以让Foo
trait 具有这些超级 trait 中定义的所有方法和行为特征,从而增强了其功能和灵活性。
假如,我们定义了一个包含 outline_print
方法的 trait OutlinePrint,我们希望它可以打印出带有星号框的值。 也就是说,如果 Point 实现了 Display trait 并返回(x, y)
,当我们调用Point(1,3)
实例的 outline_print
方法时会显示:
txt
**********
* *
* (1, 3) *
* *
**********
在 outline_print
的实现中,我们希望能够使用 Display trait 的功能。因此,我们需要指明 OutlinePrint trait 只能用于实现了 Display trait 并提供了 OutlinePrint 需要的功能的类型。 我们可以通过在 trait 定义中使用类似 OutlinePrint: Display 来做到这一点。
参考下面的例子:
rust
use std::fmt;
trait OutlinePrint: fmt::Display {
fn outline_print(&self) {
let output = self.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {} *", output);
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}
因为我们指定了 OutlinePrint trait 需要依赖 Display trait,所以我们可以在 outline_print
方法中使用 Display trait 中的 to_string
方法, 任何实现了 Display trait 的类型会实现该方法。
如果不在 trait 名后增加 :Display
并尝试在 outline_print
中调用to_string
方法,则会产生错误。 下面让我们尝试在一个没有实现 Display trait 的类型上实现 OutlinePrint trait ,看看会发生什么:
rust
struct Point {
x: i32,
y: i32,
}
impl OutlinePrint for Point {}
我们将得到类似下面的编译时错误:
error[E0277]: `Point` doesn't implement `std::fmt::Display`
我们可以通过在 Point 上实现 Display trait 来满足 OutlinePrint trait 的要求,以解决这个错误。
解决示例:
rust
use std::fmt;
trait OutlinePrint: fmt::Display {
fn outline_print(&self) {
let output = self.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {} *", output);
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}
struct Point {
x: i32,
y: i32,
}
// 实现 Display trait 来满足要求
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl OutlinePrint for Point {}
fn main() {
let p = Point { x:1, y:3 } ;
p.outline_print()
}
现在我们可以成功编译了,并可以在 Point 实例上调用outline_print
方法来显示它。