您的位置:首页 > 科技 > IT业 > java学习_东莞seo网络推广_南宁哪里有seo推广厂家_类似火脉的推广平台

java学习_东莞seo网络推广_南宁哪里有seo推广厂家_类似火脉的推广平台

2025/1/8 14:23:00 来源:https://blog.csdn.net/qq_37387199/article/details/143454914  浏览:    关键词:java学习_东莞seo网络推广_南宁哪里有seo推广厂家_类似火脉的推广平台
java学习_东莞seo网络推广_南宁哪里有seo推广厂家_类似火脉的推广平台

题目来自:https://practice-zh.course.rs/generics-traits/trait-object.html

1


trait Bird {fn quack(&self) -> String;
}struct Duck;
impl Duck {fn swim(&self) {println!("Look, the duck is swimming")}
}
struct Swan;
impl Swan {fn fly(&self) {println!("Look, the duck.. oh sorry, the swan is flying")}
}impl Bird for Duck {fn quack(&self) -> String{"duck duck".to_string()}
}impl Bird for Swan {fn quack(&self) -> String{"swan swan".to_string()}
}fn main() {// 填空let duck = __;duck.swim();let bird = hatch_a_bird(2);// 变成鸟儿后,它忘记了如何游,因此以下代码会报错// bird.swim();// 但它依然可以叫唤assert_eq!(bird.quack(), "duck duck");let bird = hatch_a_bird(1);// 这只鸟儿忘了如何飞翔,因此以下代码会报错// bird.fly();// 但它也可以叫唤assert_eq!(bird.quack(), "swan swan");println!("Success!")
}   // 实现以下函数
fn hatch_a_bird...

一个答案示例:

fn main() {// 填空let duck = Duck;duck.swim();let bird = hatch_a_bird(2);// 变成鸟儿后,它忘记了如何游,因此以下代码会报错// bird.swim();// 但它依然可以叫唤assert_eq!(bird.quack(), "duck duck");let bird = hatch_a_bird(1);// 这只鸟儿忘了如何飞翔,因此以下代码会报错// bird.fly();// 但它也可以叫唤assert_eq!(bird.quack(), "swan swan");println!("Success!")
}   // 实现以下函数
fn hatch_a_bird(num: i32) -> Box<dyn Bird>{match num {2 => Box::new(Duck),_ => Box::new(Swan)}
}

Box类似于C++的智能指针,当然,Rust没有提供传统指针(至少我还没学到),而dyn有点虚类的味道了,都是运行时语法。不过这里不能使用引用,因为没有被引用的主体。

2

trait Bird {fn quack(&self);
}struct Duck;
impl Duck {fn fly(&self) {println!("Look, the duck is flying")}
}
struct Swan;
impl Swan {fn fly(&self) {println!("Look, the duck.. oh sorry, the swan is flying")}
}impl Bird for Duck {fn quack(&self) {println!("{}", "duck duck");}
}impl Bird for Swan {fn quack(&self) {println!("{}", "swan swan");}
}fn main() {// 填空let birds __;for bird in birds {bird.quack();// 当 duck 和 swan 变成 bird 后,它们都忘了如何翱翔于天际,只记得该怎么叫唤了。。// 因此,以下代码会报错// bird.fly();}
}

这里的比喻很生动形象了,在没有声明vec的元素类型的情况下,vec只会按第一个推导;声明了vec是特征,那子类的各种自己的方法就用不了了。C++也是一样。

fn main() {// 填空let birds: Vec<Box<dyn Bird>> = vec![Box::new(Duck), Box::new(Swan)];for bird in birds {bird.quack();// 当 duck 和 swan 变成 bird 后,它们都忘了如何翱翔于天际,只记得该怎么叫唤了。。// 因此,以下代码会报错// bird.fly();}
}

3


// 填空
trait Draw {fn draw(&self) -> String;
}impl Draw for u8 {fn draw(&self) -> String {format!("u8: {}", *self)}
}impl Draw for f64 {fn draw(&self) -> String {format!("f64: {}", *self)}
}fn main() {let x = 1.1f64;let y = 8u8;// draw xdraw_with_box(__);// draw ydraw_with_ref(&y);println!("Success!")
}fn draw_with_box(x: Box<dyn Draw>) {x.draw();
}fn draw_with_ref(x: __) {x.draw();
}

答案:

fn main() {let x = 1.1f64;let y = 8u8;// draw xdraw_with_box(Box::new(x));// draw ydraw_with_ref(&y);println!("Success!")
}fn draw_with_box(x: Box<dyn Draw>) {x.draw();
}fn draw_with_ref(x: &dyn Draw) {x.draw();
}

4


trait Foo {fn method(&self) -> String;
}impl Foo for u8 {fn method(&self) -> String { format!("u8: {}", *self) }
}impl Foo for String {fn method(&self) -> String { format!("string: {}", *self) }
}// 通过泛型实现以下函数
fn static_dispatch...// 通过特征对象实现以下函数
fn dynamic_dispatch...fn main() {let x = 5u8;let y = "Hello".to_string();static_dispatch(x);dynamic_dispatch(&y);println!("Success!")
}

答案

// 通过泛型实现以下函数
fn static_dispatch<T: Foo>(t: T) -> String{t.method()
}// 通过特征对象实现以下函数
fn dynamic_dispatch(f: &dyn Foo) -> String{f.method()
}

对于C++来说,静态多态一般指的是重载,一旦涉及父类子类调用,就是动态多态的部分了,指针和引用都是一样的。

5


// 使用至少两种方法让代码工作
// 不要添加/删除任何代码行
trait MyTrait {fn f(&self) -> Self;
}impl MyTrait for u32 {fn f(&self) -> Self { 42 }
}impl MyTrait for String {fn f(&self) -> Self { self.clone() }
}fn my_function(x: Box<dyn MyTrait>)  {x.f()
}fn main() {my_function(Box::new(13_u32));my_function(Box::new(String::from("abc")));println!("Success!")
}

特征安全需要方法不能返回Self,所以第一种改法就是将所有的返回值改成Box包裹动态类型:

trait MyTrait {fn f(&self) -> Box<dyn MyTrait>;
}impl MyTrait for u32 {fn f(&self) -> Box<dyn MyTrait> { Box::new(42) }
}impl MyTrait for String {fn f(&self) -> Box<dyn MyTrait> { Box::new(self.clone()) }
}fn my_function(x: Box<dyn MyTrait>) -> Box<dyn MyTrait>{x.f()
}fn main() {my_function(Box::new(13_u32));my_function(Box::new(String::from("abc")));println!("Success!")
}

第二种和第一种类似,只不过是把所有Box改成了动态引用

trait MyTrait {fn f(&self) -> &dyn MyTrait;
}impl MyTrait for u32 {fn f(&self) -> &dyn MyTrait { &42 }
}impl MyTrait for String {fn f(&self) -> &dyn MyTrait { self }
}fn my_function(x: &dyn MyTrait) -> &dyn MyTrait{x.f()
}fn main() {my_function(&13_u32);my_function(&String::from("abc"));println!("Success!")
}

你要是问我性能差别,我只能说两种都是栈上指针,堆上数据,性能应该没啥差别

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com