默认方法让 trait 的「必须实现」降到最小,把其余功能免费送给实现者。这篇验证它的几个行为:最小实现换来多少免费能力、覆盖默认实现能省多少工作、一个编译器查不出来的陷阱(互相依赖的默认方法),以及它在 trait 对象里怎么分发。
源码:
1 | struct Countdown(u32);
2 | impl Iterator for Countdown {
3 | type Item = u32;
4 | fn next(&mut self) -> Option<u32> { if self.0 == 0 { None } else { self.0 -= 1; Some(self.0 + 1) } }
5 | }
6 | fn main() {
7 | println!("collect:{:?}", Countdown(5).collect::<Vec<_>>());
8 | println!("map + filter + sum:{}", Countdown(10).filter(|n| n % 2 == 0).map(|n| n * n).sum::<u32>());
9 | println!("zip:{:?}", Countdown(3).zip(Countdown(3).map(|n| n * 10)).collect::<Vec<_>>());
10 | println!("max:{:?},min:{:?},count:{},last:{:?}", Countdown(7).max(), Countdown(7).min(), Countdown(7).count(), Countdown(7).last());
11 | println!("fold:{},any:{},all:{},position:{:?}", Countdown(4).fold(0, |a, b| a + b), Countdown(4).any(|x| x == 3), Countdown(4).all(|x| x > 0), Countdown(9).position(|x| x == 5));
12 | println!("take_while + skip + step_by:{:?}", Countdown(20).skip(2).step_by(4).take_while(|&x| x > 3).collect::<Vec<_>>());
13 | }
编译:成功
运行(退出码 0):
collect:[5, 4, 3, 2, 1]
map + filter + sum:220
zip:[(3, 30), (2, 20), (1, 10)]
max:Some(7),min:Some(1),count:7,last:Some(1)
fold:10,any:true,all:true,position:Some(4)
take_while + skip + step_by:[18, 14, 10, 6]Iterator 的更多内容见Iterator Trait与自定义 Iterator。
源码:
1 | struct Slow { left: u32, calls: u32 }
2 | struct Fast { left: u32, calls: u32 }
3 | trait Count { fn next_value(&mut self) -> Option<u32>; fn count_all(&mut self) -> u32 { let mut n = 0; while self.next_value().is_some() { n += 1; } n } }
4 | impl Count for Slow { fn next_value(&mut self) -> Option<u32> { self.calls += 1; if self.left == 0 { None } else { self.left -= 1; Some(self.left) } } } // 用默认的 count_all:逐个数
5 | impl Count for Fast { fn next_value(&mut self) -> Option<u32> { self.calls += 1; if self.left == 0 { None } else { self.left -= 1; Some(self.left) } } fn count_all(&mut self) -> u32 { let n = self.left; self.left = 0; n } } // 覆盖:直接返回
6 | struct Q(i32);
7 | impl PartialEq for Q { fn eq(&self, o: &Q) -> bool { self.0 == o.0 } } // 只实现 eq
8 | fn main() {
9 | let mut s = Slow { left: 1000, calls: 0 }; let mut f = Fast { left: 1000, calls: 0 };
10 | let (a, b) = (s.count_all(), f.count_all());
11 | println!("默认实现:count_all = {},调用了 next_value {} 次", a, s.calls);
12 | println!("覆盖实现:count_all = {},调用了 next_value {} 次", b, f.calls);
13 | println!("Q(1) != Q(2) 来自 PartialEq 的默认方法 ne:{}", Q(1) != Q(2));
14 | }
编译:成功
运行(退出码 0):
默认实现:count_all = 1000,调用了 next_value 1001 次
覆盖实现:count_all = 1000,调用了 next_value 0 次
Q(1) != Q(2) 来自 PartialEq 的默认方法 ne:true编译: 成功 警告/错误: (无) 运行:退出码 -6(负数表示被信号终止:6);stderr 第一行:thread 'main' (7034937) has overflowed its stack
源码:
1 | trait Greeter {
2 | fn name(&self) -> String;
3 | fn greet(&self) -> String { format!("你好,{}!", self.name()) }
4 | }
5 | struct Plain; struct Formal;
6 | impl Greeter for Plain { fn name(&self) -> String { "小明".into() } }
7 | impl Greeter for Formal { fn name(&self) -> String { "王先生".into() } fn greet(&self) -> String { format!("{} 您好,欢迎光临。", self.name()) } }
8 | fn main() {
9 | let list: Vec<Box<dyn Greeter>> = vec![Box::new(Plain), Box::new(Formal)];
10 | for g in &list { println!("{}", g.greet()); }
11 | }
编译:成功
运行(退出码 0):
你好,小明!
王先生 您好,欢迎光临。trait 定义的基础见Trait 定义与实现。