泛型(generics)
rust 也有泛型,这种最早出现1970年代的Ada
语言中,后来被许多基于对象和面向对象的语言所采用,包括BETA、 C 、java。
rust 也借鉴了这一特性。
这种特性让程序有更好的通用性。
1.简单示例-结构体泛型
给结构体 Point
定义一个泛型 T
struct Point<T> {
x: T,
y: T,
}
fn main() {
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
}
不同类型泛型
代码语言:javascript复制struct Point<T, U> {
x: T,
y: U,
}
fn main() {
let both_integer = Point { x: 5, y: 10 };
let both_float = Point { x: 1.0, y: 4.0 };
let integer_and_float = Point { x: 5, y: 4.0 };
}
2.函数泛型-同方法泛型
传入什么,就返回什么类型
代码语言:javascript复制fn largest<T>(list: &[T]) -> T {
那会不会跟java一样,可以类泛型作用到方法。 rust 结构体泛型作用到 函数?
代码语言:javascript复制fn largest<T>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
println!("The largest number is {}", result);
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&char_list);
println!("The largest char is {}", result);
}
3.方法泛型
真有这个。
用法和定义同java一样。 实现一个Point 的方法,类型为T。
代码语言:javascript复制struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
fn main() {
let p = Point { x: 5, y: 10 };
println!("p.x = {}", p.x());
}
泛型指定限制(constraint) 这个例子,也是实现Point,但是类型为具体类型 f32
代码语言:javascript复制impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) self.y.powi(2)).sqrt()
}
}
结合 self 使用 注意 x 返回的是 self.x 所以是调用者 p1 自己的x
代码语言:javascript复制struct Point<X1, Y1> {
x: X1,
y: Y1,
}
impl<X1, Y1> Point<X1, Y1> {
fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {
Point {
x: self.x,
y: other.y,
}
}
}
fn main() {
let p1 = Point { x: 5, y: 10.4 };
let p2 = Point { x: "Hello", y: 'c' };
let p3 = p1.mixup(p2);
println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
}
结果:
代码语言:javascript复制p3.x = 5, p3.y = c
泛型代码的性能
Rust 通过在编译时进行泛型代码的 单态化(monomorphization)
来保证效率。
单态化是一个通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程。
java也是一样的方式,通过泛型擦除来实现,就是 泛型信息只存在于代码编译阶段,在java的运行期(已经生成字节码文件后)与泛型相关的信息会被擦除掉。 所以其实也是在编译期做文章。
总结
rust 的很多方面,都借鉴了java的总分特性,不是指泛型,而是指后面还明更多的部分,比如迭代器,用起来很丝滑。
还有如golang
部份的特性,在channel
部分,用起来,就是像golang
。