enum Operation {
Get,
Set(String),
Count
}
fn execute(op: Operation) {
match op {
Operation::Get => execute_get(),
Operation::Set(s) => execute_set(s),
Operation::Count => execute_count()
}
}
Sometimes, we want to take the decision of which implementation to use at runtime instead of letting the compiler monomorphize the code.
There’s two approaches.
If the number of possible choices is limited, an Enum can be used:
enum Operation {
Get,
Set(String),
Count
}
fn execute(op: Operation) {
match op {
Operation::Get => execute_get(),
Operation::Set(s) => execute_set(s),
Operation::Count => execute_count()
}
}
enum Operation {
Get,
Set(String),
Count
}
impl Operation {
fn execute(&self) {
match &self {
&Operation::Get => execute_get(),
&Operation::Set(s) => execute_set(s),
&Operation::Count => execute_count()
}
}
}
Try to minimise repeated matches on the Enum, if not strictly necessary.
References or raw pointers on traits, also boxes, describe so-called "trait objects".
Trait objects are a pair of pointers to a virtual function table and the data.
You can only use one trait per object
This trait must fulfill certain conditions
Object-safe traits are not allowed to require Self: Sized
All methods are object-safe
They have no type parameters
They don’t use Self
Closure traits fulfill object safety rules.
fn factory() -> Box<dyn Fn(i32) -> i32> {
let num = 5;
Box::new(move |x| x + num)
}
As trait objects know about their exact type at runtime, they support downcasts through the Any
trait.
use std::fmt::Debug;
use std::any::Any;
// Logger function for any type that implements Debug.
fn log<T: Any + Debug>(value: &T) {
let value_any = value as &dyn Any;
// try to convert our value to a String. If successful, we want to
// output the String's length as well as its value. If not, it's a
// different type: just print it out unadorned.
match value_any.downcast_ref::<String>() {
Some(as_string) => {
println!("String ({}): {}", as_string.len(), as_string);
}
None => {
println!("{:?}", value);
}
}
}
fn main() {
log(&String::from("String here"));
log(&1)
}