LearnRust/26-generics/src/main.rs

95 lines
2.9 KiB
Rust
Raw Normal View History

2024-12-22 02:06:45 +03:00
use std::fmt::Display;
// This is a struct that can take any type into it.
// Only limitation is every field should be same type.
struct Point<T> {
x_axis: T,
y_axis: T,
z_axis: T,
}
impl<T> Point<T> {
// This creates new point based from values that is given.
// Their type should be anything and must be same.
fn new(x_axis: T, y_axis: T, z_axis: T) -> Self {
Point {
x_axis,
y_axis,
z_axis,
}
}
}
// This is a struct that can take any type into it.
// Unlike "Point" its field not have to be same type but it can also be.
2024-12-22 05:08:26 +03:00
struct AnotherPoint<T, U, V> {
2024-12-22 02:06:45 +03:00
x_axis: T,
y_axis: U,
2024-12-22 05:08:26 +03:00
z_axis: V,
2024-12-22 02:06:45 +03:00
}
2024-12-22 05:08:26 +03:00
impl<T, U, V> AnotherPoint<T, U, V> {
2024-12-22 02:06:45 +03:00
// This creates new point based from values that is given.
// Their types not have to be same, they can be anything
2024-12-22 05:08:26 +03:00
fn new(x_axis: T, y_axis: U, z_axis: V) -> Self {
2024-12-22 02:06:45 +03:00
AnotherPoint {
x_axis,
y_axis,
z_axis,
}
}
}
fn main() {
println!("Hello, world!");
// It's a bit strange to explain generics without traits.
// In short trait defines a capability.
// Generics use traits to match capable things to achieve what generics used for.
// Instead of defining a lot of functions, structs and enums that do similar things,
// we define generics to match similar patterns and collapse functions, structs and enums in one.
// Values of this "Point" variables must have same type.
let point_1 = Point::new(1, 2, 3);
let point_2 = Point::new(1.0, 2.0, 3.0);
// This "AnotherPoint" type is not have limitation like "Point"
// They can be different types.
let another_point_1 = AnotherPoint::new(1, 2.0, 'a');
let another_point_2 = AnotherPoint::new(1, 2, 3);
// I can call print_point function because it's able to fit our variables
// Every field has same type in a "Point" type.
print_point(&point_1.x_axis, &point_1.y_axis, &point_1.z_axis);
print_point(&point_2.x_axis, &point_2.y_axis, &point_2.z_axis);
// I can call print_point function because it's able to fit our variables
// Every field may be different from others in "AnotherPoint" type.
print_point(
&another_point_1.x_axis,
&another_point_1.y_axis,
&another_point_1.z_axis,
);
print_point(
&another_point_2.x_axis,
&another_point_2.y_axis,
&another_point_2.z_axis,
);
}
// This function takes at most 3 different type of values.
// These values must include Display trait.
// We defined this rule with "where".
// Instead of using where we can say:
// fn print_point<T: Display, U: Display, K: Display>(x_axis: &T, y_axis: &U, z_axis: &K)
fn print_point<T, U, K>(x_axis: &T, y_axis: &U, z_axis: &K)
where
T: Display,
U: Display,
K: Display,
{
println!("{}", x_axis);
println!("{}", y_axis);
println!("{}", z_axis);
}