July 1st, 2024

Behavior Inheritance in Rust (2021)

Rust favors composition over inheritance due to limited support for traditional inheritance. To mimic behavior inheritance, developers can use a P-Impl pattern, adding a base object field and implementing a trait to access it efficiently.

Read original articleLink Icon
Behavior Inheritance in Rust (2021)

In Rust, the community often emphasizes composition over inheritance due to the lack of traditional inheritance support. While Rust allows for defining interfaces and using traits to achieve some object-oriented programming paradigms, it does not support full behavior inheritance as seen in languages like C++. This limitation became apparent when considering building a GUI toolkit in Rust, where common default behaviors across objects are essential. A workaround involves using a pattern similar to P-Impl, where a base object provides default implementations that can be composed into custom objects. By defining a trait that includes methods to access the base implementation object, developers can effectively inherit behaviors in Rust. This approach involves adding a field with the base object and implementing the trait with a function returning a reference to that field. While Rust lacks direct support for behavior inheritance, this method allows for achieving similar functionality with a manageable amount of boilerplate code.

Related

My experience crafting an interpreter with Rust (2021)

My experience crafting an interpreter with Rust (2021)

Manuel Cerón details creating an interpreter with Rust, transitioning from Clojure. Leveraging Rust's safety features, he faced challenges with closures and classes, optimizing code for performance while balancing safety.

Homegrown Rendering with Rust

Homegrown Rendering with Rust

Embark Studios develops a creative platform for user-generated content, emphasizing gameplay over graphics. They leverage Rust for 3D rendering, introducing the experimental "kajiya" renderer for learning purposes. The team aims to simplify rendering for user-generated content, utilizing Vulkan API and Rust's versatility for GPU programming. They seek to enhance Rust's ecosystem for GPU programming.

The Inconceivable Types of Rust: How to Make Self-Borrows Safe

The Inconceivable Types of Rust: How to Make Self-Borrows Safe

The article addresses Rust's limitations on self-borrows, proposing solutions like named lifetimes and inconceivable types to improve support for async functions. Enhancing Rust's type system is crucial for advanced features.

Using SIMD for Parallel Processing in Rust

Using SIMD for Parallel Processing in Rust

SIMD is vital for performance in Rust. Options include auto-vectorization, platform-specific intrinsics, and std::simd module. Balancing performance, portability, and ease of use is key. Leveraging auto-vectorization and intrinsics optimizes Rust projects for high-performance computing, multimedia, systems programming, and cryptography.

Ergonomic Self-Referential Types for Rust

Ergonomic Self-Referential Types for Rust

Yoshua Wuyts introduces Ergonomic Self-Referential Types for Rust, enhancing self-referential types accessibility. Features include self lifetimes, fixed memory locations, immovable types, and safe self-references initialization. The discussion showcases async {} and Future usage, emphasizing tracking references and potential Rust type system enhancements. Collaboration with Eric Holk is acknowledged for exploring !Move implications.

Link Icon 3 comments
By @zevv - 4 months
This is a nice example to do inheritance the Rust-way using composition instead of OO, but still I'm missing some essential parts for which I have not found the proper Rust idioms yet.

For example, when building a widget hierarchy, I would like to be able to pass widgets of different types to a function or store them in a `Vec<>`, but this is not possible since these are different concrete types.

Trait objects can help here, but then Rust lacks the machinery to upcast and downcast between types as there is no RTTI attached to these trait objects; you can not cast/convert a `Button` to a `BaseWidget`, or a `BaseWidget` that was originally a `Button` back to a `Button`.

What would be the rusty way to handle this?

By @stouset - 4 months
For what it’s worth, this exact pattern is essentially entirely what’s implied by “composition over inheritance”.

Nice to have a concise example written down though.