Rust nie ma natywnego wsparcia dla OOP, ale i tak możesz użyć tych technik, aby skorzystać z paradygmatu.

Programowanie zorientowane obiektowo (OOP) upraszcza projektowanie oprogramowania, kładąc nacisk na użycie obiektów do reprezentowania rzeczywistych bytów i koncepcji. OOP zachęca do konserwacji poprzez enkapsulację funkcjonalności w obiektach.

Rust to elastyczny język, który obsługuje programowanie funkcjonalne i proceduralne. Chociaż nie obsługuje natywnie programowania obiektowego, można zaimplementować koncepcje OOP przy użyciu wbudowanych typów danych Rusta.

Hermetyzacja w Rust

Hermetyzacja polega na organizowaniu kodu w samodzielne jednostki, które ukrywają wewnętrzne szczegóły udostępnienie interfejsu publicznego do interakcji zewnętrznych w celu zminimalizowania złożoności i ulepszenia kodu łatwość konserwacji.

Możesz hermetyzować kod Rusta za pomocą modułów. Moduł to zbiór elementów, w tym funkcje, struktury, wyliczenia i stałe. Moduły Rust zapewniają funkcjonalność grupowania i definiowania granic między częściami programu.

instagram viewer

Używanie modułów do enkapsulacji danych i funkcji

Możesz zdefiniować moduł za pomocą mod słowo kluczowe, po którym następuje nazwa:

mod mój_moduł {
// elementy modułu idą tutaj
}

Moduły można organizować hierarchicznie, zagnieżdżając ich deklaracje:

mod moduł nadrzędny {
mod mój_moduł {
// elementy modułu idą tutaj
}
}

Następnie możesz odwoływać się do zagnieżdżonych modułów z pełną hierarchią, oddzielając każdy moduł podwójnym dwukropkiem, na przykład nadrzędny_moduł:: mój_moduł.

Domyślnie elementy w modułach są prywatne i dostępne tylko dla kodu w ramach tego samego modułu. Ale możesz upublicznić moduły za pomocą pub słowo kluczowe:

mod mój_moduł {
pubprzypmoja_funkcja() {
// treść funkcji idzie tutaj
}
}

Następnie możesz uzyskać dostęp moja_funkcja z innych części programu.

Używanie cech do definiowania zachowań

Innym sposobem, w jaki Rust umożliwia enkapsulację, jest użycie cech. Cechy definiują zachowania, które typy mogą implementować i zapewniają, że różne typy są zgodne z tym samym interfejsem.

pubcechaNadający się do druku {
przypwydrukować(&samego siebie);
}

pubstrukturaMój typ {
// pola strukturalne tutaj
}

implik Nadający się do druku Do Mój typ {
przypwydrukować(&samego siebie) {
// implementacja tutaj
}
}

The Nadający się do druku cecha ma wydrukować metoda i tzw Mój typ struct implementuje Nadający się do druku cechę poprzez wdrożenie wydrukować metoda.

Używając cech, możesz upewnić się, że każdy typ, który implementuje Nadający się do druku cecha ma wydrukować metoda. Jest to przydatne podczas pracy z kodem ogólnym, który musi współpracować z różnymi typami o wspólnym zachowaniu.

Dziedziczenie w Rust

Dziedziczenie pozwala zdefiniować jedną klasę na podstawie innej. Podklasa odziedziczy właściwości i metody swojego rodzica.

W Rust zachęca się do używania kompozycji zamiast dziedziczenia. Kompozycja to proces tworzenia nowych obiektów poprzez łączenie istniejących. Zamiast tworzyć nową klasę, która dziedziczy funkcjonalność z klasy bazowej, można utworzyć nową strukturę zawierającą instancję struktury podstawowej i jej pola.

Tworzenie nowych typów przez łączenie istniejących typów

Będziesz używać wyliczeń i struktur do tworzenia nowych typów. Wyliczenia są przydatne w przypadku typów o skończonych wartościach, a struktury mogą zawierać wiele pól.

Możesz utworzyć typ wyliczeniowy dla różnych typów zwierząt.

wyliczenieZwierzę {
Kot,
Pies,
Ptak,
// ...
}

Alternatywnie możesz utworzyć strukturę zawierającą pola dla każdego typu zwierzęcia. Struktury mogą zawierać wyliczenia i inne typy.

strukturaZwierzę {
nazwa: Strunowy,
wiek: u8,
typ_zwierzęcia: typ zwierzęcia,
}

wyliczenietyp zwierzęcia {
Kot,
Pies,
Ptak,
// ...
}

The Zwierzę struct przechowuje wartości typ zwierzęcia typ wyliczeniowy.

Możesz użyć cech, aby zaimplementować dziedziczenie i dodać zachowanie do typu bez tworzenia nowego.

cechaLatać {
przyplatać(&samego siebie);
}

Oto jak możesz zaimplementować Latać cecha dla wielu typów.

strukturaPtak {
nazwa: Strunowy,
rozpiętość skrzydeł: f32,
}

implik Latać Do ptak {
przyplatać(&samego siebie) {
drukuj!("{} lata!", samego siebie.nazwa);
}
}

strukturaSamolot {
Model: Strunowy,
maksymalna prędkość: u32,
}

implik Latać Do Samolot {
przyplatać(&samego siebie) {
drukuj!("{} lata!", samego siebie.Model);
}
}

The Ptak I Samolot struktury implementują Latać cecha i wydrukuj ciągi z Drukuj! makro.

Możesz zadzwonić do latać metoda na obu strukturach bez znajomości ich konkretnych typów.

przypgłówny() {
pozwalać ptak = ptak {
nazwa: Strunowy::z("Orzeł"),
rozpiętość skrzydeł: 2.0,
};

pozwalać samolot = samolot {
Model: Strunowy::z("Boeinga 747"),
maksymalna prędkość: 900,
};

pozwalać latające_obiekty: Vecdyn Leć> = vec![&ptak, &samolot];

Do obiekt W latające_obiekty {
obiekt.fly();
}
}

The główny funkcja tworzy instancję Samolot I Ptak typy. The latające_obiekty wektor jest wektorem instancji obiektu, a wektor Do pętla przechodzi przez wektor i wywołuje metodę latać metoda na instancjach.

Implementacja polimorfizmu w Rust

Klasa lub typ jest polimorficzny, jeśli wiele typów reprezentuje interfejs. Ponieważ cechy zapewniają funkcjonalność do definiowania zachowań w Rust, zapewniając jednocześnie wspólny interfejs do pisania ogólnego kodu, możesz użyć Traits do implementacji polimorfizmu.

Oto cecha o nazwie Do rysowania który definiuje zachowanie renderowania obiektów na ekranie:

cechaDo rysowania {
przyprysować(&samego siebie);
}

Typy, które implementują cechę Drawable, mogą uzyskiwać dostęp do rysować funkcjonować.

strukturaProstokąt {
szerokość: u32,
wysokość: u32,
}

implik Do rysowania Do prostokąt {
przyprysować(&samego siebie) {
// Renderuj prostokąt na ekranie
}
}

Możesz napisać ogólny kod, który rysuje obiekty, które implementują Do rysowania cecha.

przyprysuj_obiekt(obiekt: &T) {
obiekt.draw();
}

The rysuj_obiekt funkcja przyjmuje typ ogólny T jako dane wejściowe, które implementują Do rysowania cecha i nazywa rysować metoda na cechę. Różne obiekty mogą implementować Do rysowania cechę i uzyskać dostęp do funkcji.

Implementacja abstrakcji w Rust

Abstrakcja to koncepcja OOP gdzie klasy i interfejsy są dostępne dla określonych obiektów i typów. Możesz zaimplementować abstrakcję w Rust z cechami.

Oto przykładowa cecha odtwarzacza multimedialnego:

cechaGłoska bezdźwięczna {
przypgrać(&samego siebie);
}

Struktury i wyliczenia, które implementują Głoska bezdźwięczna cecha musi zapewniać implementację dla grać metoda.

strukturaPiosenka {
tytuł: Strunowy,
artysta: Strunowy,
}

implik Głoska bezdźwięczna Do Piosenka {
przypgrać(&samego siebie) {
drukuj!(„Odtwarzam utwór: {} autorstwa {}”, samego siebie.tytuł, samego siebie.artysta);
}
}

The Piosenka struct implementuje Głoska bezdźwięczna cechę, dostarczając implementację dla grać metoda, która drukuje komunikat z polami Piosenka struktury do konsoli.

przypgłówny() {
// Utwórz instancję struktury Song
pozwalać piosenka = piosenka {
tytuł: Strunowy::z(„Bohemian Rhapsody”),
artysta: Strunowy::z("Królowa"),
};

// Wywołaj metodę odtwarzania w instancji utworu
piosenka.graj();
}

The piosenka zmienna jest instancją Piosenka struct, a zmienna może uzyskiwać dostęp i wywoływać grać metoda.

Organizowanie kodu Rust jest łatwe

Programowanie zorientowane obiektowo pomaga w organizacji kodu. Dzięki modułowemu systemowi Rust możesz łatwo zorganizować swój kod Rust, wdrażając koncepcje OOP dla swojej aplikacji, aby Twój kod był uporządkowany, łatwy w zarządzaniu i intuicyjny.