trainings/Rust_2026/rust-bs-2026-09-14/exercises/rust-exercises/7_traits.ipynb

421 lines
8.9 KiB
Text

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Traits"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [],
"source": [
"// Fill in the two impl blocks to make the code work.\n",
"// DON'T modify the code in `main`.\n",
"trait Greetings {\n",
" fn say_hi(&self) -> String {\n",
" String::from(\"Hi\")\n",
" }\n",
"\n",
" fn say_something(&self) -> String;\n",
"}\n",
"\n",
"struct Student {}\n",
"\n",
"impl Greetings for Student {\n",
"}\n",
"\n",
"struct Teacher {}\n",
"\n",
"impl Greetings for Teacher {\n",
"}\n",
"\n",
"fn main() {\n",
" let s = Student {};\n",
" assert_eq!(s.say_hi(), \"Hi\");\n",
" assert_eq!(s.say_something(), \"I'm a good student\");\n",
"\n",
" let t = Teacher {};\n",
" assert_eq!(t.say_hi(), \"Hi, I'm your new teacher\");\n",
" assert_eq!(t.say_something(), \"I'm not a bad teacher\");\n",
"\n",
" println!(\"Success!\");\n",
"}\n",
"\n",
"main();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"2."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [],
"source": [
"struct Fender {}\n",
"struct Gibson {}\n",
"\n",
"trait Guitar {\n",
" fn sound(&self) -> String;\n",
"}\n",
"\n",
"impl Guitar for Fender {\n",
" fn sound(&self) -> String {\n",
" \"like Jimmy!\".to_string()\n",
" }\n",
"}\n",
"\n",
"impl Guitar for Gibson {\n",
" fn sound(&self) -> String {\n",
" \"like Slash!\".to_string()\n",
" }\n",
"}\n",
"\n",
"// Returns some struct that implements Guitar, but we don't know which one at compile time.\n",
"// FIX the errors here, you can make a fake random, or you can use trait object.\n",
"fn random_guitar(random_number: f64) -> impl Guitar {\n",
" if random_number < 0.5 {\n",
" Fender {}\n",
" } else {\n",
" Gibson {}\n",
" }\n",
"}\n",
"\n",
"fn main() {\n",
" let random_number = 0.234;\n",
" let guitar = random_guitar(random_number);\n",
" println!(\"You've randomly chosen an guitar, and it sounds {}\", guitar.sound());\n",
"}\n",
"\n",
"main();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"3. Trait bound"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [],
"source": [
"struct Fender {}\n",
"struct Gibson {}\n",
"\n",
"trait Guitar {\n",
" fn sound(&self) -> String;\n",
"}\n",
"\n",
"impl Guitar for Fender {\n",
" fn sound(&self) -> String {\n",
" \"like Jimmy!\".to_string()\n",
" }\n",
"}\n",
"\n",
"impl Guitar for Gibson {\n",
" fn sound(&self) -> String {\n",
" \"like Slash!\".to_string()\n",
" }\n",
"}\n",
"\n",
"\n",
"// Implement `fn use_guitar` with trait bound in two ways.\n",
"fn use_guitar<G>(g: &G) {\n",
" println!(\"Sounds {}\", g.sound());\n",
"}\n",
"\n",
"// Implement `fn sum` with trait bound in two ways.\n",
"fn sum<T>(x: T, y: T) -> T {\n",
" x + y\n",
"}\n",
"\n",
"fn main() {\n",
" let g = Fender{};\n",
" use_guitar(&g);\n",
" assert_eq!(sum(1, 2), 3);\n",
"\n",
" \n",
" println!(\"Success!\");\n",
"}\n",
"\n",
"main();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"4."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [],
"source": [
"// FIX the errors.\n",
"struct Pair<T> {\n",
" x: T,\n",
" y: T,\n",
"}\n",
"\n",
"impl<T> Pair<T> {\n",
" fn new(x: T, y: T) -> Self {\n",
" Self {\n",
" x,\n",
" y,\n",
" }\n",
" }\n",
"}\n",
"\n",
"impl<T: std::fmt::Debug + PartialOrd> Pair<T> {\n",
" fn cmp_display(&self) {\n",
" if self.x >= self.y {\n",
" println!(\"The largest member is x = {:?}\", self.x);\n",
" } else {\n",
" println!(\"The largest member is y = {:?}\", self.y);\n",
" }\n",
" }\n",
"}\n",
"\n",
"struct Unit(i32);\n",
"\n",
"fn main() {\n",
" let pair = Pair{\n",
" x: Unit(1),\n",
" y: Unit(3)\n",
" };\n",
"\n",
" pair.cmp_display();\n",
"}\n",
"\n",
"main();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"5. Array with trait objects"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [],
"source": [
"trait Guitar {\n",
" fn sound(&self);\n",
"}\n",
"\n",
"struct Stratocaster;\n",
"\n",
"impl Stratocaster {\n",
" fn get_name(&self) {\n",
" println!(\"Fender Stratocaster\");\n",
" }\n",
"}\n",
"\n",
"struct LesPaul;\n",
"\n",
"impl LesPaul {\n",
" fn get_name(&self) {\n",
" println!(\"Gibson Les Paul\");\n",
" }\n",
"}\n",
"\n",
"impl Guitar for Stratocaster {\n",
" fn sound(&self) {\n",
" println!(\"{}\", \"Sounds like Jimmy!\");\n",
" }\n",
"}\n",
"\n",
"impl Guitar for LesPaul {\n",
" fn sound(&self) {\n",
" println!(\"{}\", \"Sounds like Slash!\");\n",
" }\n",
"}\n",
"\n",
"fn main() {\n",
" // // FILL in the blank to make the code work.\n",
" let s = Stratocaster{};\n",
" let lp1 = LesPaul{};\n",
" let blacky = Stratocaster{};\n",
"\n",
" let guitars: [__; 3]= [__];\n",
"\n",
" // Iterate through the guitars and make them sound.\n",
" todo!();\n",
"}\n",
"\n",
"main();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"6. &dyn & Box<dyn>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [],
"source": [
"// FILL in the blanks.\n",
"trait Draw {\n",
" fn draw(&self) -> String;\n",
"}\n",
"\n",
"impl Draw for u8 {\n",
" fn draw(&self) -> String {\n",
" format!(\"u8: {}\", *self)\n",
" }\n",
"}\n",
"\n",
"impl Draw for f64 {\n",
" fn draw(&self) -> String {\n",
" format!(\"f64: {}\", *self)\n",
" }\n",
"}\n",
"\n",
"fn main() {\n",
" let x = 1.1f64;\n",
" let y = 8u8;\n",
"\n",
" // Draw x.\n",
" draw_with_box(__);\n",
"\n",
" // Draw y.\n",
" draw_with_ref(&y);\n",
"\n",
" println!(\"Success!\");\n",
"}\n",
"\n",
"fn draw_with_box(x: Box<__>) {\n",
" x.draw();\n",
"}\n",
"\n",
"fn draw_with_ref(x: __) {\n",
" x.draw();\n",
"}\n",
"\n",
"main();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"7. Static and Dynamic dispatch"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "rust"
}
},
"outputs": [],
"source": [
"\n",
"trait Foo {\n",
" fn method(&self) -> String;\n",
"}\n",
"\n",
"impl Foo for u8 {\n",
" fn method(&self) -> String { format!(\"u8: {}\", *self) }\n",
"}\n",
"\n",
"impl Foo for String {\n",
" fn method(&self) -> String { format!(\"string: {}\", *self) }\n",
"}\n",
"\n",
"// IMPLEMENT below with generics. (static polymorphism)\n",
"fn static_dispatch...\n",
"\n",
"// Implement below with trait objects. (dynamic polymorphism)\n",
"fn dynamic_dispatch...\n",
"\n",
"fn main() {\n",
" let x = 5u8;\n",
" let y = \"Hello\".to_string();\n",
"\n",
" static_dispatch(x);\n",
" dynamic_dispatch(&y);\n",
"\n",
" println!(\"Success!\");\n",
"}\n",
"\n",
"main();"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Rust",
"language": "rust",
"name": "rust"
},
"language_info": {
"codemirror_mode": "rust",
"file_extension": ".rs",
"mimetype": "text/rust",
"name": "Rust",
"pygment_lexer": "rust",
"version": ""
}
},
"nbformat": 4,
"nbformat_minor": 2
}