1use std::fmt::Display;
10
11pub trait Drawable {
13 fn draw(&self);
14 fn area(&self) -> f64;
15}
16
17pub struct Rectangle {
19 width: f64,
20 height: f64,
21}
22
23impl Rectangle {
24 pub fn new(width: f64, height: f64) -> Self {
25 Rectangle { width, height }
26 }
27}
28
29impl Drawable for Rectangle {
30 fn draw(&self) {
31 println!("Drawing a rectangle {}x{}", self.width, self.height);
32 }
33
34 fn area(&self) -> f64 {
35 self.width * self.height
36 }
37}
38
39pub struct Circle {
41 radius: f64,
42}
43
44impl Circle {
45 pub fn new(radius: f64) -> Self {
46 Circle { radius }
47 }
48}
49
50impl Drawable for Circle {
51 fn draw(&self) {
52 println!("Drawing a circle with radius {}", self.radius);
53 }
54
55 fn area(&self) -> f64 {
56 std::f64::consts::PI * self.radius * self.radius
57 }
58}
59
60pub struct Triangle {
62 base: f64,
63 height: f64,
64}
65
66impl Triangle {
67 pub fn new(base: f64, height: f64) -> Self {
68 Triangle { base, height }
69 }
70}
71
72impl Drawable for Triangle {
73 fn draw(&self) {
74 println!("Drawing a triangle with base {} and height {}", self.base, self.height);
75 }
76
77 fn area(&self) -> f64 {
78 0.5 * self.base * self.height
79 }
80}
81
82pub fn polymorphism_examples() {
84 println!("\nš Polymorphism Examples");
85 println!("{}", "=".repeat(25));
86
87 trait_object_polymorphism();
88 generic_polymorphism();
89 enum_polymorphism();
90 closure_polymorphism();
91 function_pointer_polymorphism();
92 advanced_trait_patterns();
93}
94
95fn trait_object_polymorphism() {
97 println!("\nšÆ Trait Object Polymorphism (Dynamic Dispatch)");
98 println!("{}", "-".repeat(35));
99
100 let shapes: Vec<Box<dyn Drawable>> = vec![
102 Box::new(Rectangle::new(10.0, 5.0)),
103 Box::new(Circle::new(3.0)),
104 Box::new(Triangle::new(8.0, 6.0)),
105 ];
106
107 println!("Drawing all shapes:");
108 for shape in &shapes {
109 shape.draw();
110 println!("Area: {:.2}", shape.area());
111 }
112
113 draw_shape(&Rectangle::new(15.0, 10.0));
115 draw_shape(&Circle::new(5.0));
116}
117
118fn draw_shape(shape: &dyn Drawable) {
119 println!("Generic draw function:");
120 shape.draw();
121 println!("Area: {:.2}", shape.area());
122}
123
124fn generic_polymorphism() {
126 println!("\nā” Generic Polymorphism (Static Dispatch)");
127 println!("{}", "-".repeat(40));
128
129 let rect = Rectangle::new(12.0, 8.0);
130 let circle = Circle::new(4.0);
131
132 draw_generic(&rect);
134 draw_generic(&circle);
135
136 print_and_draw(&rect);
138 print_and_draw(&circle);
139}
140
141fn draw_generic<T: Drawable>(shape: &T) {
142 println!("Generic function (compile-time dispatch):");
143 shape.draw();
144 println!("Area: {:.2}", shape.area());
145}
146
147fn print_and_draw<T: Drawable + std::fmt::Debug>(shape: &T) {
148 println!("Shape details: {:?}", shape);
149 shape.draw();
150}
151
152impl std::fmt::Debug for Rectangle {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 write!(f, "Rectangle {{ width: {}, height: {} }}", self.width, self.height)
156 }
157}
158
159impl std::fmt::Debug for Circle {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 write!(f, "Circle {{ radius: {} }}", self.radius)
162 }
163}
164
165impl std::fmt::Debug for Triangle {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 write!(f, "Triangle {{ base: {}, height: {} }}", self.base, self.height)
168 }
169}
170
171fn enum_polymorphism() {
173 println!("\nš Enum-based Polymorphism");
174 println!("{}", "-".repeat(25));
175
176 #[derive(Debug)]
177 enum Shape {
178 Rectangle { width: f64, height: f64 },
179 Circle { radius: f64 },
180 Triangle { base: f64, height: f64 },
181 }
182
183 impl Shape {
184 fn draw(&self) {
185 match self {
186 Shape::Rectangle { width, height } => {
187 println!("Drawing rectangle {}x{}", width, height);
188 }
189 Shape::Circle { radius } => {
190 println!("Drawing circle with radius {}", radius);
191 }
192 Shape::Triangle { base, height } => {
193 println!("Drawing triangle with base {} and height {}", base, height);
194 }
195 }
196 }
197
198 fn area(&self) -> f64 {
199 match self {
200 Shape::Rectangle { width, height } => width * height,
201 Shape::Circle { radius } => std::f64::consts::PI * radius * radius,
202 Shape::Triangle { base, height } => 0.5 * base * height,
203 }
204 }
205 }
206
207 let shapes = vec![
208 Shape::Rectangle { width: 10.0, height: 5.0 },
209 Shape::Circle { radius: 3.0 },
210 Shape::Triangle { base: 8.0, height: 6.0 },
211 ];
212
213 for shape in &shapes {
214 shape.draw();
215 println!("Area: {:.2}", shape.area());
216 println!("Debug: {:?}", shape);
217 println!();
218 }
219}
220
221fn closure_polymorphism() {
223 println!("\nš§ Closure Polymorphism");
224 println!("{}", "-".repeat(25));
225
226 let add = |x: i32, y: i32| x + y;
228 let multiply = |x: i32, y: i32| x * y;
229 let subtract = |x: i32, y: i32| x - y;
230
231 fn apply_operation<F>(x: i32, y: i32, op: F) -> i32
233 where
234 F: Fn(i32, i32) -> i32
235 {
236 op(x, y)
237 }
238
239 println!("5 + 3 = {}", apply_operation(5, 3, add));
240 println!("5 * 3 = {}", apply_operation(5, 3, multiply));
241 println!("5 - 3 = {}", apply_operation(5, 3, subtract));
242
243 let multiplier = 10;
245 let scale = |x: i32| x * multiplier;
246 println!("Scaling 5 by {}: {}", multiplier, scale(5));
247}
248
249fn function_pointer_polymorphism() {
251 println!("\nš Function Pointer Polymorphism");
252 println!("{}", "-".repeat(25));
253
254 fn add(x: i32, y: i32) -> i32 { x + y }
255 fn multiply(x: i32, y: i32) -> i32 { x * y }
256
257 fn execute_operation(x: i32, y: i32, op: fn(i32, i32) -> i32) -> i32 {
259 op(x, y)
260 }
261
262 println!("Using function pointers:");
263 println!("5 + 3 = {}", execute_operation(5, 3, add));
264 println!("5 * 3 = {}", execute_operation(5, 3, multiply));
265
266 let operations: [fn(i32, i32) -> i32; 2] = [add, multiply];
268 for (i, op) in operations.iter().enumerate() {
269 println!("Operation {}: 4, 7 = {}", i, op(4, 7));
270 }
271}
272
273fn advanced_trait_patterns() {
275 println!("\nš Advanced Trait Patterns");
276 println!("{}", "-".repeat(40));
277
278 trait Iterator2 {
280 type Item;
281 fn next(&mut self) -> Option<Self::Item>;
282 }
283
284 trait Greet {
286 fn name(&self) -> &str;
287
288 fn greet(&self) -> String {
289 format!("Hello, {}!", self.name())
290 }
291
292 fn formal_greet(&self) -> String {
293 format!("Good day, {}.", self.name())
294 }
295 }
296
297 struct Person {
298 name: String,
299 }
300
301 impl Greet for Person {
302 fn name(&self) -> &str {
303 &self.name
304 }
305
306 fn greet(&self) -> String {
308 format!("Hey there, {}!", self.name())
309 }
310 }
311
312 let person = Person { name: "Alice".to_string() };
313 println!("{}", person.greet());
314 println!("{}", person.formal_greet());
315
316 fn complex_function<T, U>(_t: T, _u: U)
318 where
319 T: Display + Clone,
320 U: Clone + std::fmt::Debug,
321 {
322 println!("Complex function with multiple trait bounds");
323 }
324
325 complex_function("hello", 42);
326}
327