0
0
Rustprogramming~20 mins

Trait objects overview in Rust - Practice Problems & Coding Challenges

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
Rust Trait Objects Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2:00remaining
What is the output of this Rust code using a trait object?

Consider the following Rust code that uses a trait object to call a method on different types:

Rust
trait Speak {
    fn speak(&self) -> String;
}

struct Dog;
struct Cat;

impl Speak for Dog {
    fn speak(&self) -> String {
        String::from("Woof")
    }
}

impl Speak for Cat {
    fn speak(&self) -> String {
        String::from("Meow")
    }
}

fn animal_speak(animal: &dyn Speak) {
    println!("{}", animal.speak());
}

fn main() {
    let dog = Dog;
    let cat = Cat;
    animal_speak(&dog);
    animal_speak(&cat);
}
AWoof\nMeow
BMeow\nMeow
CWoof\nWoof
DMeow\nWoof
Attempts:
2 left
💡 Hint

Remember that the trait object calls the method implemented for the actual type.

🧠 Conceptual
intermediate
1:30remaining
What is a key limitation of trait objects in Rust?

Which of the following is a limitation when using trait objects in Rust?

ATrait objects can be copied freely without ownership concerns.
BTrait objects allow storing multiple types without any restrictions.
CTrait objects cannot be used with traits that have generic methods.
DTrait objects require the trait to be implemented only for primitive types.
Attempts:
2 left
💡 Hint

Think about what kind of methods can be called through a trait object.

🔧 Debug
advanced
2:30remaining
Why does this Rust code fail to compile when using a trait object?

Examine the code below and identify why it fails to compile:

Rust
trait Draw {
    fn draw(&self);
    fn resize<T>(&self, scale: T);
}

struct Circle;

impl Draw for Circle {
    fn draw(&self) {
        println!("Drawing a circle");
    }
    fn resize<T>(&self, scale: T) {
        println!("Resizing circle");
    }
}

fn paint(shape: &dyn Draw) {
    shape.draw();
}

fn main() {
    let c = Circle;
    paint(&c);
}
AThe method draw is missing a return type, causing a compilation error.
BThe trait Draw is not object safe because it has a generic method, so it cannot be used as a trait object.
CThe struct Circle does not implement the Draw trait correctly because it lacks a constructor.
DThe function paint requires ownership of the shape, but a reference is provided.
Attempts:
2 left
💡 Hint

Check the trait methods and their signatures for object safety rules.

📝 Syntax
advanced
1:30remaining
Which option correctly creates a boxed trait object in Rust?

Given the trait Speak and struct Dog implementing it, which code snippet correctly creates a boxed trait object?

Rust
trait Speak {
    fn speak(&self) -> String;
}

struct Dog;

impl Speak for Dog {
    fn speak(&self) -> String {
        String::from("Woof")
    }
}

fn main() {
    // Which line correctly creates a boxed trait object?
}
Alet pet: Box<dyn Speak> = Dog::new();
Blet pet: Box<Speak> = Box::new(Dog);
Clet pet: Box<dyn Speak> = Box::new(&Dog);
Dlet pet: Box<dyn Speak> = Box::new(Dog);
Attempts:
2 left
💡 Hint

Remember the syntax for trait objects and boxing in Rust.

🚀 Application
expert
2:00remaining
How many items are in the vector after this Rust code runs?

Consider this Rust code that stores different types implementing a trait in a vector of trait objects:

Rust
trait Animal {
    fn name(&self) -> &str;
}

struct Dog;
struct Cat;

impl Animal for Dog {
    fn name(&self) -> &str { "Dog" }
}

impl Animal for Cat {
    fn name(&self) -> &str { "Cat" }
}

fn main() {
    let mut animals: Vec<Box<dyn Animal>> = Vec::new();
    animals.push(Box::new(Dog));
    animals.push(Box::new(Cat));
    animals.push(Box::new(Dog));
    animals.push(Box::new(Cat));
    animals.pop();
    animals.push(Box::new(Dog));
    println!("Number of animals: {}", animals.len());
}
A4
B2
C5
D3
Attempts:
2 left
💡 Hint

Count the pushes and pops carefully to find the final length.