TL ; DR:
Rust has no abstract classes. Its closest equivalent is a trait: a template that declares methods with no body, which any concrete type that implements the trait must provide. You can't create a value of a trait itself, only of a type that implements it.
trait Animal {
fn speak(&self); // abstract — must be implemented by concrete types
}
struct Dog;
impl Animal for Dog {
fn speak(&self) { println!("Woof"); }
}
Full lesson:
Sometimes you want to capture shared behavior across a family of types without committing to one concrete implementation. For example, every Animal can speak(), but exactly how depends on whether it's a Dog or a Cat. That's what abstract classes are for in other languages, and what traits are for in Rust.
Two superpowers
- You can't create a bare
Animalvalue — a trait is not a type you can build. You have to pick a concrete type that implements it. - Any type that implements the trait MUST provide every method that has no default body, or the compiler reports an error. The trait is a contract with teeth.
Mixing abstract and concrete
A trait can also have default methods (with bodies). Those are shared by every implementing type for free. Only the methods declared without a body must be implemented. A trait cannot hold fields; the data lives in the structs.
Notes by language
- Required method — write the signature followed by a semicolon:
fn speak(&self);. - Default method — give it a body inside the trait; implementing types may keep it or replace it.
- Implementing — write
impl Animal for Dog { ... }. There is noabstractoroverridekeyword.
Your task
The Animal trait is already defined. Declare a unit struct Dog (struct Dog;) and write impl Animal for Dog with a speak method that prints "Woof". mainFunction builds a Dog and calls speak().
Expected output:
WoofFree plan: 30 tutor messages. PRO is unlimited.
