Rust 创建泛型
// generic_function.rs
fn give_me<T>(value: T) {
let _ = value;
}
fn main() {
let a = "generics";
let b = 1024;
give_me(a);
give_me(b);
}
泛型结构体
// generic_struct.rs
struct GenericStruct<T>(T);
struct Container<T> {
item: T
}
fn main() {
// stuff
}
泛型枚举
// generic_enum.rs
enum Transmission<T> {
Signal(T),
NoSignal
}
fn main() {
// stuff
}
Rust 泛型实现
// generic_struct_impl.rs
struct Container<T> {
item: T
}
impl<T> Container<T> {
fn new(item: T) -> Self {
Container { item }
}
}
fn main() {
// stuff
}
Rust 泛型应用
// using_generic_vec.rs
fn main() {
// 提供一种类型
let v1: Vec<u8> = Vec::new();
// 或者调用某个方法
let mut v2 = Vec::new();
v2.push(2); // 现在v2的类型是Vec<i32>
// 或者使用turbofish符号
let v3 = Vec::<u8>::new(); // 不是那么容易理解
}
Rust 特征
关联方法:这些方法可以直接在实现特征的类型上使用,并不需要类型的实例来调用。在主流的编程语言中,这也被称为静态方法,例如标准库的特征FromStr的from_str方法。
实例方法:这些方法需要将self作为其第一个参数。这仅适用于实现特征的类型实例,self将指向实现特征的类型实例。
// super_player/src/main.rs
struct Audio(String);
struct Video(String);
impl Playable for Audio {
fn play(&self) {
println!("Now playing: {}", self.0);
}
}
impl Playable for Video {
fn play(&self) {
println!("Now playing: {}", self.0);
}
}
fn main() {
println!("Super player!");
let audio = Audio("ambient_music.mp3".to_string());
let video = Video("big_buck_bunny.mkv".to_string());
audio.play();
video.play();
}
// super_player/src/media.rs
pub trait Playable {
fn play(&self);
fn pause() {
println!("Paused");
}
}
// trait_inheritance.rs
trait Vehicle {
fn get_price(&self) -> u64;
}
trait Car: Vehicle {
fn model(&self) -> String;
}
struct TeslaRoadster {
model: String,
release_date: u16
}
impl TeslaRoadster {
fn new(model: &str, release_date: u16) -> Self {
Self { model: model.to_string(), release_date }
}
}
impl Car for TeslaRoadster {
fn model(&self) -> String {
"Tesla Roadster I".to_string()
}
}
impl Vehicle for TeslaRoadster {
fn get_price(&self) -> u64 {
200_000
}
}
fn main() {
let my_roadster = TeslaRoadster::new("Tesla Roadster II", 2020);
println!("{} is priced at ${}", my_roadster.model,
my_roadster.get_price());
}
特征的多种形式
标记特征
简单特征
trait Foo {
fn foo();
}
泛型特征
pub trait From<T> {
fn from(T) -> Self;
}
关联类型特征
trait Foo {
type Out;
fn get_value(self) -> Self::Out;
}
继承特征
trait Bar {
fn bar();
}
trait Foo: Bar {
fn foo();
}
使用包含泛型的特征——特征区间
struct Game;
struct Enemy;
struct Hero;
impl Game {
fn load<T>(&self, entity: T) {
entity.init();
}
}
fn main() {
let game = Game;
game.load(Enemy);
game.load(Hero);
}
必须在泛型声明旁边放置几个符号来指定特征 ,特征区间
struct Game;
struct Enemy;
struct Hero;
trait Loadable {
fn init(&self);
}
impl Loadable for Enemy {
fn init(&self) {
println!("Enemy loaded");
}
}
impl Loadable for Hero {
fn init(&self) {
println!("Hero loaded");
}
}
impl Game {
fn load<T: Loadable>(&self, entity: T) { // 特征区间
entity.init();
}
}
fn main() {
let game = Game;
game.load(Enemy);
game.load(Hero);
}
使用标准库特征区间
use std::ops::Add;
fn add_thing<T: Add>(fst: T, snd: T) {
let _ = fst + snd;
}
fn main() {
add_thing(2, 2);
}
区间内泛型
fn show_me<T: Display>(val: T) {
// 可以使用 {}格式化字符串, 因为有 Display特征区间
println!("{}", val);
}
where语句
pub fn parse<F>(&self) -> Result<F, <F as FromStr>::Err> where F: FromStr { ... }
类型上的特征区间
use std::fmt::Display;
struct Foo<T: Display> {
bar: T
}
// or
struct Bar<F> where F: Display {
inner: F
}
fn main() {}
泛型函数和impl代码块上的特征区间
use std::fmt::Debug;
trait Eatable {
fn eat(&self);
}
#[derive(Debug)]
struct Food<T>(T);
#[derive(Debug)]
struct Apple;
impl<T> Eatable for Food<T> where T: Debug {
fn eat(&self) {
println!("Eating {:?}", self);
}
}
fn eat<T>(val: T) where T: Eatable {
val.eat();
}
fn main() {
let apple = Food(Apple);
eat(apple);
}
使用“+”将特征组合为区间
impl<K: Hash + Eq, V> HashMap<K, V, RandomState>
trait Eat {
fn eat(&self) {
println!("eat");
}
}
trait Code {
fn code(&self) {
println!("code");
}
}
trait Sleep {
fn sleep(&self) {
println!("sleep");
}
}
trait Programmer : Eat + Code + Sleep {
fn animate(&self) {
self.eat();
self.code();
self.sleep();
println!("repeat!");
}
}
struct Bob;
impl Programmer for Bob {}
impl Eat for Bob {}
impl Code for Bob {}
impl Sleep for Bob {}
fn main() {
Bob.animate();
}
特征区间与impl特征语法
声明特征区间的另一种语法是impl特征语法,它是编译器的最新特性
use std::fmt::Display;
fn show_me(val: impl Display) {
println!("{}", val);
}
fn main() {
show_me("Trait bounds are awesome");
}
fn lazy_adder(a:u32, b: u32) -> impl Fn() ->
u32 {
move || a + b
}
fn main() {
let add_later = lazy_adder(1024, 2048);
println!("{:?}", add_later());
}
use std::fmt::Display;
fn surround_with_braces(val: impl Display) ->
impl Display {
format!("{{{}}}", val)
}
fn main() {
println!("{}", surround_with_braces("Hello"));
}
标准库特征简介
#[derive(Default)]
struct Complex<T> {
//实部
re: T,
//虚部
im: T
}
impl<T> Complex<T> {
fn new(re: T, im: T) -> Self {
Complex { re, im }
}
}
#[cfg(test)]
mod tests {
use Complex;
#[test]
fn complex_basics() {
let first = Complex::new(3,5);
let second: Complex<i32> = Complex::default();
assert_eq!(first.re, 3);
assert_eq!(first.im, 5);
assert!(second.re == second.im);
}
}
Debug 特征有助于在控制台上输出类型以便进行调试。
PartialEq和Eq:特征允许两个元素相互比较以验证是否相等。
Copy和Clone:特征定义了类型的复制方式。
#[derive(Default, Debug, PartialEq, Copy, Clone)]
struct Complex<T> {
// 实部
re: T,
//虚部
im: T
}
impl<T> Complex<T> {
fn new(re: T, im: T) -> Self {
Complex { re, im }
}
}
impl<T: Add<T, Output=T>> Add for Complex<T>
{
type Output = Complex<T>;
fn add(self, rhs: Complex<T>) -> Self::Output {
Complex { re: self.re + rhs.re, im: self.im + rhs.im }
}
}
#[cfg(test)]
mod tests {
use Complex;
#[test]
fn complex_basics() {
let first = Complex::new(3,5);
let second: Complex<i32> =
Complex::default();
}
fn complex_addition() {
let a = Complex::new(1,-2);
let b = Complex::default();
let res = a + b;
assert_eq!(res, a);
}
}
use std::convert::From;
impl<T> From<(T, T)> for Complex<T> {
fn from(value: (T, T)) -> Complex<T> {
Complex { re: value.0, im: value.1 }
}
}
// 其他impl代码块被省略了
#[cfg(test)]
mod tests {
// 其他测试
use Complex;
#[test]
fn complex_from() {
let a = (2345, 456);
let complex = Complex::from(a);
assert_eq!(complex.re, 2345);
assert_eq!(complex.im, 456);
}
}
// 为了表述简洁,前面的代码已经省略
use std::fmt::{Formatter, Display, Result};
impl<T: Display> Display for Complex<T> {
fn fmt(&self, f: &mut Formatter) ->
Result {
write!(f, "{} + {}i", self.re, self.im)
}
}
#[cfg(test)]
mod tests {
// other tests
use Complex;
#其他测试
fn complex_display() {
let my_imaginary = Complex::new(2345,456);
println!("{}", my_imaginary);
}
}
使用特征对象实现真正的多态性
use std::fmt::Debug;
#[derive(Debug)]
struct Square(f32);
#[derive(Debug)]
struct Rectangle(f32, f32);
trait Area: Debug {
fn get_area(&self) -> f32;
}
impl Area for Square {
fn get_area(&self) -> f32 {
self.0 * self.0
}
}
impl Area for Rectangle {
fn get_area(&self) -> f32 {
self.0 * self.1
}
}
fn main() {
let shapes: Vec<&dyn Area> = vec![&Square(3f32), &Rectangle(4f32,2f32)];
for s in shapes {
println!("{:?}", s);
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)