What is Polymorphism?
In a dynamic language like Python, we don’t have to do anything special to allow a function to accept arguments of different types:
def print_value(val):
print(val)
print_value(123)
print_value("hello")
print_value({})
But Rust’s static type system requires us to specify the types of our functions’ arguments:
fn print_value(val: i32) {
println!("{}", val);
}
fn main() {
print_value(123);
// print_value("hello"); // ❌ Mismatched types!
}
-
If you are coming from a dynamic language like Python, the concept of polymorphism may be new to you because in dynamic languages all functions are implicitly polymorphic. But in Rust, functions only accept arguments of the exact types they expect, and we must use a mechanism like generics to support polymorphism.
-
Static typing is a powerful tool that allows the compiler to enforce correct usage of our APIs: If your function needs to be given an
i32in order to function correctly, the compiler won’t allow a user of that function to pass in a string. -
But static typing is restrictive in cases where we want to write code that is flexible in its handling of types. In the example on this slide, we might want our
print_valuefunction to be able to print both numbers and strings, but as written it can only accepti32values. -
Edit
print_valueto make it generic usingDisplayto print different kinds of values:#![allow(unused)] fn main() { fn print_value(val: impl std::fmt::Display) { println!("{}", val); } }