8.13 Function Overloading (or Lack Thereof)
Some languages allow function overloading, where multiple functions can share the same name but differ in the number or types of their parameters. The compiler selects the correct function based on the arguments provided at the call site.
Rust does not support function overloading in the traditional sense. Within a given scope, all functions must have unique names. You cannot define two functions named process
where one takes an i32
and the other takes a &str
.
Rust achieves similar goals using other mechanisms:
-
Generics: As seen in Section 8.8, a single generic function can work with multiple types, provided they meet the required trait bounds.
use std::fmt::Display; // One generic function instead of multiple overloaded versions. fn print_value<T: Display>(value: T) { println!("Value: {}", value); } fn main() { print_value(10); // Works with i32 print_value("hello"); // Works with &str print_value(3.14); // Works with f64 }
-
Traits: Traits define shared behavior. Different types can implement the same trait, providing their own versions of the methods defined by that trait. This allows calling the same method name (
.draw()
in the example below) on different types.trait Draw { fn draw(&self); } struct Button { label: String } struct Icon { name: String } impl Draw for Button { fn draw(&self) { println!("Drawing button: [{}]", self.label); } } impl Draw for Icon { fn draw(&self) { println!("Drawing icon: <{}>", self.name); } } fn main() { let button = Button { label: "Submit".to_string() }; let icon = Icon { name: "Save".to_string() }; button.draw(); // Calls Button's implementation of draw icon.draw(); // Calls Icon's implementation of draw }
While not identical to overloading, generics and traits provide powerful, type-safe ways to achieve polymorphism and code reuse in Rust.