默认方法
特征默认实现
默认方法 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。
带函数体的方法
特征方法不必只有签名。特征可以提供默认实现——实现者会自动获得的方法体。
这能减少许多类型中的样板代码。
默认方法
直接在特征中编写方法体。实现该特征的类型会免费继承它,无需额外代码。
trait Greet {
fn hello(&self) -> String {
String::from("Hello there")
}
}
struct Robot;
impl Greet for Robot {}
fn main() {
println!("{}", Robot.hello());
}覆盖默认实现
任何实现者都可以通过提供自己的版本来覆盖默认实现。对于该类型,覆盖版本会取代默认版本。
trait Greet {
fn hello(&self) -> String { String::from("Hello there") }
}
struct Robot;
struct Pirate;
impl Greet for Robot {}
impl Greet for Pirate {
fn hello(&self) -> String { String::from("Arr!") }
}
fn main() {
println!("{}", Robot.hello());
println!("{}", Pirate.hello());
}默认实现调用必需方法
默认方法可以调用同一特征的其他方法,即使这些方法没有默认实现。这是一种强大的模式:实现者提供一个小型核心,默认实现则在其上构建更丰富的行为。
trait Summary {
fn title(&self) -> String;
fn preview(&self) -> String {
format!("Read more about: {}", self.title())
}
}
struct Article { headline: String }
impl Summary for Article {
fn title(&self) -> String { self.headline.clone() }
}
fn main() {
let a = Article { headline: String::from("Rust Rocks") };
println!("{}", a.preview());
}模板方法模式
这种必需方法加默认实现的组合称为模板方法模式。特征在默认实现中定义整体流程,并将可变部分留给必需方法。
trait Report {
fn body(&self) -> String;
fn render(&self) -> String {
format!("=== REPORT ===\n{}\n==============", self.body())
}
}
struct Sales;
impl Report for Sales {
fn body(&self) -> String { String::from("Sales up 10%") }
}
fn main() {
println!("{}", Sales.render());
}多个默认实现
特征可以自由混合必需方法和默认方法。实现者只需提供必需的方法。
trait Animal {
fn name(&self) -> String;
fn legs(&self) -> u32 { 4 }
fn describe(&self) -> String {
format!("{} has {} legs", self.name(), self.legs())
}
}
struct Dog;
impl Animal for Dog {
fn name(&self) -> String { String::from("Dog") }
}
fn main() {
println!("{}", Dog.describe());
}默认实现与标准特征
许多标准特征都依赖默认实现。例如,Iterator 只要求实现 next;每个适配器和使用者都是基于它构建的默认方法。
这就是为什么一个方法就能解锁整套工具的原因。
为提升性能而覆盖
有时默认实现可以正常工作,但专用版本会更快。实现者可以只覆盖该方法,同时保留其余默认实现。
trait Counter {
fn items(&self) -> Vec<i32>;
fn total(&self) -> i32 {
self.items().iter().sum()
}
}
struct Fast { precomputed: i32 }
impl Counter for Fast {
fn items(&self) -> Vec<i32> { vec![] }
fn total(&self) -> i32 { self.precomputed }
}
fn main() {
println!("{}", Fast { precomputed: 99 }.total());
}让特征易于使用
良好的特征设计是:只要求实现少量方法,并为其余方法提供方便的默认实现。实现者只需完成最少的工作,却能获得丰富的接口。
注意事项
默认方法只能使用其他特征方法,以及通过这些方法访问 self 背后的类型;它不能直接访问未知实现者的字段。请围绕特征自身的方法设计默认实现。
默认方法与必需方法一览
带方法体的特征方法是默认方法;只有签名的方法是必需方法。实现者必须提供每个必需方法,但可以不修改默认方法。
trait Logger {
fn line(&self) -> String;
fn log(&self) {
println!("LOG: {}", self.line());
}
}
struct App;
impl Logger for App {
fn line(&self) -> String { String::from("started") }
}
fn main() {
App.log();
}快速检查
检验您对默认方法的理解。
回顾
您学习了特征的默认实现:
- 特征方法可以包含方法体,作为默认实现
- 实现者可以免费继承它,也可以覆盖它
- 默认实现可以调用必需方法,从而实现模板方法模式
- 只保留少量必需方法,就能让特征易于使用
常见问题解答
「默认方法」课时是免费的吗?
是的 — 「默认方法」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。
「默认方法」这节课中我会学到什么?
特征默认实现 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「默认方法」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。