泛型跟在方法名后
fn say_hello(out: &mut dyn Write) // 普通函数
fn say_hello<W: Write>(out: &mut W) // 泛型函数
可以明确写出泛型
say_hello::<File>(&mut local_file)?
同时多个
fn top_ten<T: Debug + Hash + Eq>(values: &Vec<T>) { ... }
where语法
fn run_query<M, R>(data: &DataSet, map: M, reduce: R) -> Results where M: Mapper + Serialize, R: Reducer + Serialize{ ... }
生命周期+范型
fn nearest<'t, 'c, P>(target: &'t P, candidates: &'c [P]) -> &'c P where P: MeasureDistance{}
范型别名:
type PancakeResult<T> = Result<T, PancakeError>;
常量泛型
dot_product::<3>([0.2, 0.4, 0.6], [0., 0., 1.]);
Box包装了一层引用,这样,vec内的存的其实是Box的引用,这样,一个引用的大小区间是固定的,所以在编译期间就知道了。固定大小很重要吗,为什么要在编译期间知道,因为:
对于动态大小类型(如 dyn Trait),由于其大小在编译时未知,无法直接在栈上分配。因此,我们使用堆分配来处理这些类型,并使用固定大小的指针(如 Box)来引用它们。这样,编译器只需知道指针的大小,而不需要知道实际对象的大小。
struct Salad {
veggies: Vec<Box<dyn Vegetable>>
}
指定泛型
let _ = std::cmp::min::<i32>(3, 4);
实现trait的范型,泛型跟在impl后面 ,对于每个 实现了 Write 的类型 W,这里有一个适用于 W 的 WriteHtml 实现:
impl<W: Write> WriteHtml for W {
泛型中的Self和结构体中的Self
在泛型和特征中,Self 关键字用来指代实现该特征的具体类型。它在定义特征方法时非常有用,尤其是在需要返回实现该特征的类型时。
在结构体和实现块中,Self 关键字用来指代当前的实现类型。它在定义关联函数或方法时非常有用,可以简化代码的书写。
struct MyStruct {
value: i32,
}
impl MyStruct {
fn new(value: i32) -> Self { // 这里的 Self 代表 MyStruct
Self { value } // 这里的 Self 也是 MyStruct
}
fn get_value(&self) -> i32 {
self.value
}
}
fn main() {
let instance = MyStruct::new(42);
println!("The value is: {}", instance.get_value());
}
特型继承:
trait Creature: Visible {}
表示:每个实现了 Creature 的类型也必须实现 Visible 特型。
impl Visible for Broom {
...
}
impl Creature for Broom {
...
}
子特型不会继承 其超特型的关联项,如果你想调用超特型的方法,那么仍然要保证每 个特型都在作用域内。
trait ParentTrait {
type AssociatedType;
fn parent_method(&self);
}
trait ChildTrait: ParentTrait {
fn child_method(&self);
}
struct MyStruct;
impl ParentTrait for MyStruct {
type AssociatedType = i32;
fn parent_method(&self) {
println!("Parent method");
}
}
impl ChildTrait for MyStruct {
fn child_method(&self) {
println!("Child method");
}
}
fn main() {
let instance = MyStruct;
instance.child_method();
instance.parent_method(); // 需要显式地调用 ParentTrait 的方法
}
在这个例子中,ChildTrait 继承自 ParentTrait,但 ChildTrait 并没有自动继承 ParentTrait 的关联类型 AssociatedType 或方法 parent_method。如果你想调用 parent_method,你必须显式地将 ParentTrait 带入作用域。
trait ParentTrait {
type AssociatedType;
fn parent_method(&self);
}
trait ChildTrait: ParentTrait {
fn child_method(&self);
}
struct MyStruct;
impl ParentTrait for MyStruct {
type AssociatedType = i32;
fn parent_method(&self) {
println!("Parent method");
}
}
impl ChildTrait for MyStruct {
fn child_method(&self) {
println!("Child method");
self.parent_method(); // 显式地调用 ParentTrait 的方法
}
}
fn main() {
let instance = MyStruct;
instance.child_method(); // 这将调用 child_method 和 parent_method
}
在这个例子中,ChildTrait 的 child_method 显式地调用了 ParentTrait 的 parent_method。这表明,即使 ChildTrait 继承自 ParentTrait,你仍然需要显式地调用父特征的方法。
范型继承:
fn unknown_words<S: StringSet>(document: &[String], wordlist: &S) -> S {...}
切片引用,切片内是引用
&[&str]
trait type :
impl Iterator for Args {
type Item = String;
fn next(&mut self) -> Option<String> {
Some("good".to_string())
}
}
它能生成 String 值,因此这个 impl 声明了 type Item = String;下面的用法真的好啊:
fn collect_into_vector<I: Iterator>(iter: I) -> Vec<I::Item> {
let mut results = Vec::new();
for value in iter {
results.push(value);
}
results
}
I指定了范型,但边界是Iterator,因为I是trait,有个Item,可以直接引用I::Item。明确写出 collect_into_vector 的返回类型, 而 Item 关联类型是唯一的途径。但是如果Item想要打印{:?}的话:
fn dump<I>(iter: I) where I: Iterator, I::Item: Debug {
}
如果是String:
fn dump<I>(iter: I) where I: Iterator<Item=String> {
}
Iterator<Item=String> 本身就是一个特型。如果将 Iterator 视为所有迭代器类型的全集,那么 Iterator<Item=String> 就 是 Iterator 的子集:生成 String 的迭代器类型的集合。
fn dump(iter: &mut dyn Iterator<Item=String>) {
for (index, s) in iter.enumerate() {
println!("{}: {:?}", index, s);
}
}
以及:
trait Pattern {
type Match;
fn search(&self, string: &str) -> Option<Self::Match>;
}
/// 你可以在字符串中找一个特定的字符
impl Pattern for char {
type Match = usize;
/// Match只是找到的字符的位置
fn search(&self, string: &str) -> Option<usize> {
Some(3)
}
}
trait和struct中的Self
当你为一个结构体实现一个特征时,Self 关键字指的是实现该特征的具体类型。在你的例子中,当你为结构体 Ps 实现特征 MyIteratorTrait 时,Self 关键字指的就是 Ps。
trait MyIteratorTrait<Opp:OpTrait> {
type Item;
fn new(t:i32) -> Self;
fn show_item<I>(&self, t:I) -> Opp where I:Iterator, I::Item:Debug;
}
struct Ps{
value:i32
}
trait OpTrait{
}
struct Op{name:String}
impl OpTrait for Op {
}
impl MyIteratorTrait<Op> for Ps {
type Item = String;
fn new(value:i32) -> Self{
Ps{value }
}
fn show_item<I>(&self, t: I) -> Op
where
I: Iterator,
I::Item: Debug
{
// vec![self.value.to_string()]
Op{name:self.value.to_string()}
}
}
fn main() {
let ps: Ps = Ps::new(32);
let vecc = vec![32];
ps.show_item(vecc.into_iter());
}
既然是泛型则能使用泛型相关:
fn print<T: Display>(val: T) {
println!("{}", val);
}
fn print(val: impl Display) {
println!("{}", val);
}
使用泛型时允许函数的调用者指定泛型参数的 类型,比如 print::<i32>(42),而如果使用 impl Trait 则不 能这样做。
下面这样也行:
trait Ord: Eq + PartialOrd<Self> {
fn cmp(&self, other: &Self) -> Ordering;
}