How to Replace OOP in Rust?

Introduction

First, let’s recall the main principles of OOP:

  • Inheritance
  • Encapsulation
  • Polymorphism

While there are no issues with encapsulation in Rust, developers who have worked with OOP languages like Python might face difficulties implementing the remaining principles. This is especially relevant for those who decided to rewrite a project from a language like Python/Kotlin to Rust.

Inheritance

What is inheritance? Inheritance is a mechanism that allows extending and overriding the functionality of a type. Let’s look at each idea separately.

Extending Functionality

Let’s consider an example in Python.

<span>class</span> <span>Employee</span><span>:</span>
<span>def</span> <span>__init__</span><span>(</span><span>self</span><span>,</span> <span>name</span><span>:</span> <span>str</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
<span>self</span><span>.</span><span>name</span> <span>=</span> <span>name</span>
<span>def</span> <span>say_name</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
<span>print</span><span>(</span><span>self</span><span>.</span><span>name</span><span>)</span>
<span>class</span> <span>Programmer</span><span>(</span><span>Employee</span><span>):</span>
<span>pass</span>
<span>if</span> <span>__name__</span> <span>==</span> <span>"</span><span>__main__</span><span>"</span><span>:</span>
<span>programmer</span> <span>=</span> <span>Programmer</span><span>(</span><span>"</span><span>Jack</span><span>"</span><span>)</span>
<span>programmer</span><span>.</span><span>say_name</span><span>()</span>
<span>class</span> <span>Employee</span><span>:</span>
    <span>def</span> <span>__init__</span><span>(</span><span>self</span><span>,</span> <span>name</span><span>:</span> <span>str</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
        <span>self</span><span>.</span><span>name</span> <span>=</span> <span>name</span>

    <span>def</span> <span>say_name</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
        <span>print</span><span>(</span><span>self</span><span>.</span><span>name</span><span>)</span>


<span>class</span> <span>Programmer</span><span>(</span><span>Employee</span><span>):</span>
    <span>pass</span>


<span>if</span> <span>__name__</span> <span>==</span> <span>"</span><span>__main__</span><span>"</span><span>:</span>
    <span>programmer</span> <span>=</span> <span>Programmer</span><span>(</span><span>"</span><span>Jack</span><span>"</span><span>)</span>
    <span>programmer</span><span>.</span><span>say_name</span><span>()</span>
class Employee: def __init__(self, name: str) -> None: self.name = name def say_name(self) -> None: print(self.name) class Programmer(Employee): pass if __name__ == "__main__": programmer = Programmer("Jack") programmer.say_name()

Enter fullscreen mode Exit fullscreen mode

Extension means that the child class will have all the functionality of the parent. However, this is easily addressed with composition. How would it look in Rust:

<span>struct</span> <span>Employee</span> <span>{</span>
<span>name</span><span>:</span> <span>String</span><span>,</span>
<span>}</span>
<span>impl</span> <span>Employee</span> <span>{</span>
<span>fn</span> <span>say_name</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
<span>println!</span><span>(</span><span>"{}"</span><span>,</span> <span>self</span><span>.name</span><span>);</span>
<span>}</span>
<span>}</span>
<span>struct</span> <span>Programmer</span> <span>{</span>
<span>employee</span><span>:</span> <span>Employee</span><span>,</span>
<span>}</span>
<span>impl</span> <span>Programmer</span> <span>{</span>
<span>fn</span> <span>say_name</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
<span>self</span><span>.employee</span><span>.say_name</span><span>();</span>
<span>}</span>
<span>}</span>
<span>fn</span> <span>main</span><span>()</span> <span>{</span>
<span>let</span> <span>programmer</span> <span>=</span> <span>Programmer</span> <span>{</span>
<span>employee</span><span>:</span> <span>Employee</span> <span>{</span>
<span>name</span><span>:</span> <span>"Jack"</span><span>.to_string</span><span>(),</span>
<span>},</span>
<span>};</span>
<span>programmer</span><span>.say_name</span><span>();</span>
<span>}</span>
<span>struct</span> <span>Employee</span> <span>{</span>
    <span>name</span><span>:</span> <span>String</span><span>,</span>
<span>}</span>

<span>impl</span> <span>Employee</span> <span>{</span>
    <span>fn</span> <span>say_name</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
        <span>println!</span><span>(</span><span>"{}"</span><span>,</span> <span>self</span><span>.name</span><span>);</span>
    <span>}</span>
<span>}</span>

<span>struct</span> <span>Programmer</span> <span>{</span>
    <span>employee</span><span>:</span> <span>Employee</span><span>,</span>
<span>}</span>

<span>impl</span> <span>Programmer</span> <span>{</span>
    <span>fn</span> <span>say_name</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
        <span>self</span><span>.employee</span><span>.say_name</span><span>();</span>
    <span>}</span>
<span>}</span>

<span>fn</span> <span>main</span><span>()</span> <span>{</span>
    <span>let</span> <span>programmer</span> <span>=</span> <span>Programmer</span> <span>{</span>
        <span>employee</span><span>:</span> <span>Employee</span> <span>{</span>
            <span>name</span><span>:</span> <span>"Jack"</span><span>.to_string</span><span>(),</span>
        <span>},</span>
    <span>};</span>
    <span>programmer</span><span>.say_name</span><span>();</span>
<span>}</span>
struct Employee { name: String, } impl Employee { fn say_name(&self) { println!("{}", self.name); } } struct Programmer { employee: Employee, } impl Programmer { fn say_name(&self) { self.employee.say_name(); } } fn main() { let programmer = Programmer { employee: Employee { name: "Jack".to_string(), }, }; programmer.say_name(); }

Enter fullscreen mode Exit fullscreen mode

It may seem that there is some code duplication here. However, the key advantage is that the child object doesn’t need to inherit all the functionality from the parent, thus avoiding the creation of superclasses. Moreover, Rust has crates that minimize code duplication.

Overriding Functionality

Let’s look at another example in Python

<span>from</span> <span>abc</span> <span>import</span> <span>ABC</span><span>,</span> <span>abstractmethod</span>
<span>class</span> <span>Employee</span><span>(</span><span>ABC</span><span>):</span>
<span>@abstractmethod</span>
<span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
<span>pass</span>
<span>class</span> <span>Programmer</span><span>(</span><span>Employee</span><span>):</span>
<span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
<span>print</span><span>(</span><span>"</span><span>*coding...*</span><span>"</span><span>)</span>
<span>class</span> <span>ProductManager</span><span>(</span><span>Employee</span><span>):</span>
<span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
<span>print</span><span>(</span><span>"</span><span>*doing nothing*</span><span>"</span><span>)</span>
<span>if</span> <span>__name__</span> <span>==</span> <span>"</span><span>__main__</span><span>"</span><span>:</span>
<span>programmer</span> <span>=</span> <span>Programmer</span><span>()</span>
<span>product_manager</span> <span>=</span> <span>ProductManager</span><span>()</span>
<span>programmer</span><span>.</span><span>work</span><span>()</span>
<span>product_manager</span><span>.</span><span>work</span><span>()</span>
<span>from</span> <span>abc</span> <span>import</span> <span>ABC</span><span>,</span> <span>abstractmethod</span>


<span>class</span> <span>Employee</span><span>(</span><span>ABC</span><span>):</span>
    <span>@abstractmethod</span>
    <span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
        <span>pass</span>


<span>class</span> <span>Programmer</span><span>(</span><span>Employee</span><span>):</span>
    <span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
        <span>print</span><span>(</span><span>"</span><span>*coding...*</span><span>"</span><span>)</span>


<span>class</span> <span>ProductManager</span><span>(</span><span>Employee</span><span>):</span>
    <span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
        <span>print</span><span>(</span><span>"</span><span>*doing nothing*</span><span>"</span><span>)</span>


<span>if</span> <span>__name__</span> <span>==</span> <span>"</span><span>__main__</span><span>"</span><span>:</span>
    <span>programmer</span> <span>=</span> <span>Programmer</span><span>()</span>
    <span>product_manager</span> <span>=</span> <span>ProductManager</span><span>()</span>

    <span>programmer</span><span>.</span><span>work</span><span>()</span>
    <span>product_manager</span><span>.</span><span>work</span><span>()</span>
from abc import ABC, abstractmethod class Employee(ABC): @abstractmethod def work(self) -> None: pass class Programmer(Employee): def work(self) -> None: print("*coding...*") class ProductManager(Employee): def work(self) -> None: print("*doing nothing*") if __name__ == "__main__": programmer = Programmer() product_manager = ProductManager() programmer.work() product_manager.work()

Enter fullscreen mode Exit fullscreen mode

I intentionally made the Employee class abstract. This is one of the interesting features in Python, allowing you to create something akin to interfaces for child classes.

In Rust, this is solved more elegantly with traits. Let’s see how it would look in Rust:

<span>struct</span> <span>Programmer</span> <span>{}</span>
<span>struct</span> <span>ProductManager</span> <span>{}</span>
<span>trait</span> <span>Employee</span> <span>{</span>
<span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>);</span>
<span>}</span>
<span>impl</span> <span>Employee</span> <span>for</span> <span>Programmer</span> <span>{</span>
<span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
<span>println!</span><span>(</span><span>"*coding...*"</span><span>);</span>
<span>}</span>
<span>}</span>
<span>impl</span> <span>Employee</span> <span>for</span> <span>ProductManager</span> <span>{</span>
<span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
<span>println!</span><span>(</span><span>"*doing nothing*"</span><span>);</span>
<span>}</span>
<span>}</span>
<span>fn</span> <span>main</span><span>()</span> <span>{</span>
<span>let</span> <span>programmer</span> <span>=</span> <span>Programmer</span> <span>{};</span>
<span>let</span> <span>product_manager</span> <span>=</span> <span>ProductManager</span> <span>{};</span>
<span>programmer</span><span>.work</span><span>();</span>
<span>product_manager</span><span>.work</span><span>();</span>
<span>}</span>
<span>struct</span> <span>Programmer</span> <span>{}</span>

<span>struct</span> <span>ProductManager</span> <span>{}</span>

<span>trait</span> <span>Employee</span> <span>{</span>
    <span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>);</span>
<span>}</span>

<span>impl</span> <span>Employee</span> <span>for</span> <span>Programmer</span> <span>{</span>
    <span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
        <span>println!</span><span>(</span><span>"*coding...*"</span><span>);</span>
    <span>}</span>
<span>}</span>

<span>impl</span> <span>Employee</span> <span>for</span> <span>ProductManager</span> <span>{</span>
    <span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
        <span>println!</span><span>(</span><span>"*doing nothing*"</span><span>);</span>
    <span>}</span>
<span>}</span>

<span>fn</span> <span>main</span><span>()</span> <span>{</span>
    <span>let</span> <span>programmer</span> <span>=</span> <span>Programmer</span> <span>{};</span>
    <span>let</span> <span>product_manager</span> <span>=</span> <span>ProductManager</span> <span>{};</span>

    <span>programmer</span><span>.work</span><span>();</span>
    <span>product_manager</span><span>.work</span><span>();</span>
<span>}</span>
struct Programmer {} struct ProductManager {} trait Employee { fn work(&self); } impl Employee for Programmer { fn work(&self) { println!("*coding...*"); } } impl Employee for ProductManager { fn work(&self) { println!("*doing nothing*"); } } fn main() { let programmer = Programmer {}; let product_manager = ProductManager {}; programmer.work(); product_manager.work(); }

Enter fullscreen mode Exit fullscreen mode

Additionally, traits can have default implementations for functions to avoid code duplication if the same behavior is needed for multiple structures.
Defining functionality through interfaces is also more elegant because there’s no need to inherit all the functionality again. You can assign functionality “pointwise” to different structures, and a single structure can implement multiple different traits.

Polymorphism

Let’s first define what polymorphism is. Polymorphism is a mechanism where a function or structure can work with different data types that implement a common interface.

In Python, this is done quite easily, just specify the base class as the type of the object (although given that you can pass anything as an argument, you might not even need to do this ):

<span>from</span> <span>abc</span> <span>import</span> <span>ABC</span><span>,</span> <span>abstractmethod</span>
<span>class</span> <span>Employee</span><span>(</span><span>ABC</span><span>):</span>
<span>@abstractmethod</span>
<span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
<span>pass</span>
<span>class</span> <span>Programmer</span><span>(</span><span>Employee</span><span>):</span>
<span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
<span>print</span><span>(</span><span>"</span><span>*coding...*</span><span>"</span><span>)</span>
<span>class</span> <span>ProductManager</span><span>(</span><span>Employee</span><span>):</span>
<span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
<span>print</span><span>(</span><span>"</span><span>*doing nothing*</span><span>"</span><span>)</span>
<span>def</span> <span>make_work</span><span>(</span><span>worker</span><span>:</span> <span>Employee</span><span>):</span>
<span>worker</span><span>.</span><span>work</span><span>()</span>
<span>if</span> <span>__name__</span> <span>==</span> <span>"</span><span>__main__</span><span>"</span><span>:</span>
<span>programmer</span> <span>=</span> <span>Programmer</span><span>()</span>
<span>product_manager</span> <span>=</span> <span>ProductManager</span><span>()</span>
<span>make_work</span><span>(</span><span>programmer</span><span>)</span>
<span>make_work</span><span>(</span><span>product_manager</span><span>)</span>
<span>from</span> <span>abc</span> <span>import</span> <span>ABC</span><span>,</span> <span>abstractmethod</span>


<span>class</span> <span>Employee</span><span>(</span><span>ABC</span><span>):</span>
    <span>@abstractmethod</span>
    <span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
        <span>pass</span>


<span>class</span> <span>Programmer</span><span>(</span><span>Employee</span><span>):</span>
    <span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
        <span>print</span><span>(</span><span>"</span><span>*coding...*</span><span>"</span><span>)</span>


<span>class</span> <span>ProductManager</span><span>(</span><span>Employee</span><span>):</span>
    <span>def</span> <span>work</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span>
        <span>print</span><span>(</span><span>"</span><span>*doing nothing*</span><span>"</span><span>)</span>


<span>def</span> <span>make_work</span><span>(</span><span>worker</span><span>:</span> <span>Employee</span><span>):</span>
    <span>worker</span><span>.</span><span>work</span><span>()</span>


<span>if</span> <span>__name__</span> <span>==</span> <span>"</span><span>__main__</span><span>"</span><span>:</span>
    <span>programmer</span> <span>=</span> <span>Programmer</span><span>()</span>
    <span>product_manager</span> <span>=</span> <span>ProductManager</span><span>()</span>

    <span>make_work</span><span>(</span><span>programmer</span><span>)</span>
    <span>make_work</span><span>(</span><span>product_manager</span><span>)</span>
from abc import ABC, abstractmethod class Employee(ABC): @abstractmethod def work(self) -> None: pass class Programmer(Employee): def work(self) -> None: print("*coding...*") class ProductManager(Employee): def work(self) -> None: print("*doing nothing*") def make_work(worker: Employee): worker.work() if __name__ == "__main__": programmer = Programmer() product_manager = ProductManager() make_work(programmer) make_work(product_manager)

Enter fullscreen mode Exit fullscreen mode

In Rust, there are several ways to achieve this. I will talk about the two most commonly used methods.
For virtual calls in Rust, there is a special mechanism using the dyn keyword. How would this code look in Rust:

<span>struct</span> <span>Programmer</span> <span>{}</span>
<span>struct</span> <span>ProductManager</span> <span>{}</span>
<span>trait</span> <span>Employee</span> <span>{</span>
<span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>);</span>
<span>}</span>
<span>impl</span> <span>Employee</span> <span>for</span> <span>Programmer</span> <span>{</span>
<span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
<span>println!</span><span>(</span><span>"*coding...*"</span><span>);</span>
<span>}</span>
<span>}</span>
<span>impl</span> <span>Employee</span> <span>for</span> <span>ProductManager</span> <span>{</span>
<span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
<span>println!</span><span>(</span><span>"*doing nothing*"</span><span>);</span>
<span>}</span>
<span>}</span>
<span>fn</span> <span>make_work</span><span>(</span><span>worker</span><span>:</span> <span>Box</span><span><</span><span>dyn</span> <span>Employee</span><span>></span><span>)</span> <span>{</span>
<span>worker</span><span>.work</span><span>();</span>
<span>}</span>
<span>fn</span> <span>main</span><span>()</span> <span>{</span>
<span>let</span> <span>programmer</span> <span>=</span> <span>Programmer</span> <span>{};</span>
<span>let</span> <span>product_manager</span> <span>=</span> <span>ProductManager</span> <span>{};</span>
<span>make_work</span><span>(</span><span>Box</span><span>::</span><span>new</span><span>(</span><span>programmer</span><span>));</span>
<span>make_work</span><span>(</span><span>Box</span><span>::</span><span>new</span><span>(</span><span>product_manager</span><span>));</span>
<span>}</span>
<span>struct</span> <span>Programmer</span> <span>{}</span>

<span>struct</span> <span>ProductManager</span> <span>{}</span>

<span>trait</span> <span>Employee</span> <span>{</span>
    <span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>);</span>
<span>}</span>

<span>impl</span> <span>Employee</span> <span>for</span> <span>Programmer</span> <span>{</span>
    <span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
        <span>println!</span><span>(</span><span>"*coding...*"</span><span>);</span>
    <span>}</span>
<span>}</span>

<span>impl</span> <span>Employee</span> <span>for</span> <span>ProductManager</span> <span>{</span>
    <span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
        <span>println!</span><span>(</span><span>"*doing nothing*"</span><span>);</span>
    <span>}</span>
<span>}</span>

<span>fn</span> <span>make_work</span><span>(</span><span>worker</span><span>:</span> <span>Box</span><span><</span><span>dyn</span> <span>Employee</span><span>></span><span>)</span> <span>{</span>
    <span>worker</span><span>.work</span><span>();</span>
<span>}</span>

<span>fn</span> <span>main</span><span>()</span> <span>{</span>
    <span>let</span> <span>programmer</span> <span>=</span> <span>Programmer</span> <span>{};</span>
    <span>let</span> <span>product_manager</span> <span>=</span> <span>ProductManager</span> <span>{};</span>

    <span>make_work</span><span>(</span><span>Box</span><span>::</span><span>new</span><span>(</span><span>programmer</span><span>));</span>
    <span>make_work</span><span>(</span><span>Box</span><span>::</span><span>new</span><span>(</span><span>product_manager</span><span>));</span>
<span>}</span>
struct Programmer {} struct ProductManager {} trait Employee { fn work(&self); } impl Employee for Programmer { fn work(&self) { println!("*coding...*"); } } impl Employee for ProductManager { fn work(&self) { println!("*doing nothing*"); } } fn make_work(worker: Box<dyn Employee>) { worker.work(); } fn main() { let programmer = Programmer {}; let product_manager = ProductManager {}; make_work(Box::new(programmer)); make_work(Box::new(product_manager)); }

Enter fullscreen mode Exit fullscreen mode

But this is not the only way. By avoiding pointer indirection, we can achieve better performance. To avoid this, we can use enum.
Performance is higher in this case as it uses simple pattern matching instead of pointer indirection. Let’s look at an example:

<span>enum</span> <span>Employee</span> <span>{</span>
<span>Programmer</span><span>,</span>
<span>ProductManager</span><span>,</span>
<span>}</span>
<span>impl</span> <span>Employee</span> <span>{</span>
<span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
<span>match</span> <span>*</span><span>self</span> <span>{</span>
<span>Employee</span><span>::</span><span>Programmer</span> <span>=></span> <span>println!</span><span>(</span><span>"*coding...*"</span><span>),</span>
<span>Employee</span><span>::</span><span>ProductManager</span> <span>=></span> <span>println!</span><span>(</span><span>"*doing nothing*"</span><span>),</span>
<span>}</span>
<span>}</span>
<span>}</span>
<span>fn</span> <span>make_work</span><span>(</span><span>worker</span><span>:</span> <span>Employee</span><span>)</span> <span>{</span>
<span>worker</span><span>.work</span><span>();</span>
<span>}</span>
<span>fn</span> <span>main</span><span>()</span> <span>{</span>
<span>let</span> <span>programmer</span> <span>=</span> <span>Employee</span><span>::</span><span>Programmer</span><span>;</span>
<span>let</span> <span>product_manager</span> <span>=</span> <span>Employee</span><span>::</span><span>ProductManager</span><span>;</span>
<span>make_work</span><span>(</span><span>programmer</span><span>);</span>
<span>make_work</span><span>(</span><span>product_manager</span><span>);</span>
<span>}</span>
<span>enum</span> <span>Employee</span> <span>{</span>
    <span>Programmer</span><span>,</span>
    <span>ProductManager</span><span>,</span>
<span>}</span>

<span>impl</span> <span>Employee</span> <span>{</span>
    <span>fn</span> <span>work</span><span>(</span><span>&</span><span>self</span><span>)</span> <span>{</span>
        <span>match</span> <span>*</span><span>self</span> <span>{</span>
            <span>Employee</span><span>::</span><span>Programmer</span> <span>=></span> <span>println!</span><span>(</span><span>"*coding...*"</span><span>),</span>
            <span>Employee</span><span>::</span><span>ProductManager</span> <span>=></span> <span>println!</span><span>(</span><span>"*doing nothing*"</span><span>),</span>
        <span>}</span>
    <span>}</span>
<span>}</span>

<span>fn</span> <span>make_work</span><span>(</span><span>worker</span><span>:</span> <span>Employee</span><span>)</span> <span>{</span>
    <span>worker</span><span>.work</span><span>();</span>
<span>}</span>

<span>fn</span> <span>main</span><span>()</span> <span>{</span>
    <span>let</span> <span>programmer</span> <span>=</span> <span>Employee</span><span>::</span><span>Programmer</span><span>;</span>
    <span>let</span> <span>product_manager</span> <span>=</span> <span>Employee</span><span>::</span><span>ProductManager</span><span>;</span>

    <span>make_work</span><span>(</span><span>programmer</span><span>);</span>
    <span>make_work</span><span>(</span><span>product_manager</span><span>);</span>
<span>}</span>
enum Employee { Programmer, ProductManager, } impl Employee { fn work(&self) { match *self { Employee::Programmer => println!("*coding...*"), Employee::ProductManager => println!("*doing nothing*"), } } } fn make_work(worker: Employee) { worker.work(); } fn main() { let programmer = Employee::Programmer; let product_manager = Employee::ProductManager; make_work(programmer); make_work(product_manager); }

Enter fullscreen mode Exit fullscreen mode

Conclusion

Rust has all the necessary tools to rewrite an old project that was written using OOP principles. Moreover, if you use traits correctly, the result will be much more elegant. Additionally, inheritance in OOP can be a bad pattern as child classes often inherit attributes and methods that they don’t use.

原文链接:How to Replace OOP in Rust?

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
No one can change another. But one can be the reason for another to change.
没人能改变另一个人,但是某个人能成为一个人改变的原因
评论 抢沙发

请登录后发表评论

    暂无评论内容