Rust OOP Features
Rust also supports object-oriented programming - encapsulation.
Trait
Trait is something like interface that defines the prototype of a behavior, but different in that the traits are not type.
For example Clone
trait defines the deep copy of an object.
Trait Bound
Trait bound is a set of traits that the type must implement.
Supertrait
Supertrait is similar to trait bound, but applies to a trait instead.
Associated Type
Traits can have associated types.
They are similar to generic types, but totally different.
Generic types are a part of a trait - for example, Trait<T>
and Trait<S>
are different trait.
However, an associated type is a type placeholder that the implementor must specify the concrete type.
Trait Object
Trait object is something like polymorphism. It encapsulates the actual type and only exposes the trait implementing.
Unlike generic types, its concrete type will be determined at runtime. It is called dynamic dispatch, compared to static dispatch. Dispatch is a procedure of constructing vtable.
Object Safety
In order to be a trait object, the trait must be object-safe. Fundamentally object safety is the ability to construct a vtable - all dispatchable methods only have sized types as arguments and return types.
A trait is object safe if it has the following qualities.
- All supertraits must able to be object safe.
Sized
must not be a supertrait (since trait object is dynamically sized).- It must not have any associated constants.
- It must not have any associated types with generics.
- All associated functions must either be dispatchable from a trait object or be explicitly non-dispatchable
- Dispatchable functions are:
- Not have any type parameters (although lifetime parameters are allowed).
- Be a method that does not use Self except in the type of the receiver.
- Have a receiver with one of the following types:
&Self
(i.e. &self)&mut Self
(i.e &mut self)Box<Self>
Rc<Self>
Arc<Self>
Pin<P>
where P is one of the types above
- Does not have a
where Self: Sized
bound.
- Explicitly non-dispatchable functions require:
- Have a
where Self: Sized
bound.
- Have a
- Dispatchable functions are:
About Inheritance
Rust do not support inheritance; instead you should use composition. Inheritance has recently fallen out of favor as a programming design solution in many programming languages because it’s often at risk of sharing more code than necessary. Subclasses shouldn’t always share all characteristics of their parent class but will do so with inheritance. This can make a program’s design less flexible. It also introduces the possibility of calling methods on subclasses that don’t make sense or that cause errors because the methods don’t apply to the subclass. In addition, some languages will only allow single inheritance, further restricting the flexibility of a program’s design.