Rust saknar inbyggt stöd för OOP men du kan använda dessa tekniker för att dra fördel av paradigmet ändå.

Objektorienterad programmering (OOP) förenklar mjukvarudesign genom att betona användningen av objekt för att representera verkliga enheter och koncept. OOP uppmuntrar underhåll genom att kapsla in funktionalitet i objekt.

Rust är ett flexibelt språk som stöder funktionell och procedurprogrammering. Även om det inte stöder objektorienterad programmering inbyggt, kan du implementera OOP-koncept med hjälp av Rusts inbyggda datatyper.

Inkapsling i rost

Inkapsling innebär att organisera kod i fristående enheter som döljer interna detaljer samtidigt exponera ett offentligt gränssnitt för extern interaktion för att minimera komplexiteten och förbättra koden underhållbarhet.

Du kan kapsla in rostkod med moduler. En modul är en samling objekt inklusive funktioner, strukturer, uppräkningar och konstanter. Rustmoduler tillhandahåller funktionalitet för att gruppera och definiera gränser mellan delar av ett program.

instagram viewer

Använda moduler för att kapsla in data och funktioner

Du kan definiera en modul med hjälp av mod nyckelord följt av ett namn:

mod min_modul {
// modulobjekt finns här
}

Du kan organisera moduler hierarkiskt genom att kapsla deras deklarationer:

mod parent_module {
mod min_modul {
// modulobjekt finns här
}
}

Du kan sedan referera till kapslade moduler med hela hierarkin, separera varje modul med ett dubbelt kolon, till exempel, parent_module:: min_modul.

Som standard är objekt inom moduler privata och endast tillgängliga för kod inom samma modul. Men du kan göra moduler offentliga med hjälp av pub nyckelord:

mod min_modul {
pubfnmin_funktion() {
// funktionskropp går här
}
}

Du kan då komma åt min_funktion från andra delar av ditt program.

Använda egenskaper för att definiera beteenden

Ett annat sätt som Rust möjliggör inkapsling är genom att använda egenskaper. Egenskaper definierar beteenden som typer kan implementera och säkerställer att olika typer överensstämmer med samma gränssnitt.

pubdragTryckbar {
fnskriva ut(&själv);
}

pubstrukturMin typ {
// struct-fält här
}

impl Tryckbar för Min typ {
fnskriva ut(&själv) {
// implementering här
}
}

De Tryckbar egenskap har en skriva ut metoden och Min typ struct implementerar Tryckbar egenskap genom att implementera skriva ut metod.

Med hjälp av egenskaper kan du säkerställa att alla typer som implementerar Tryckbar egenskap har en skriva ut metod. Detta är praktiskt när man arbetar med generisk kod som måste samverka med olika typer som delar ett gemensamt beteende.

Arv i Rust

Arv låter dig definiera en klass baserat på en annan. Underklassen kommer att ärva egenskaperna och metoderna från sin överordnade.

I Rust uppmuntras du att använda komposition istället för arv. Komposition är en process för att skapa nya objekt genom att kombinera befintliga. Istället för att skapa en ny klass som ärver funktionalitet från basklassen, kan du skapa en ny struktur som innehåller en instans av basstrukturen och dess fält.

Skapa nya typer genom att kombinera befintliga typer

Du kommer att använda uppräkningar och strukturer för att skapa nya typer. Enums är praktiska för typer med ändliga värden, och strukturer kan innehålla flera fält.

Du kan skapa en uppräkningstyp för olika typer av djur.

uppräkningDjur {
Katt,
Hund,
Fågel,
// ...
}

Alternativt kan du skapa en struktur som innehåller fält för varje djurtyp. Strukturer kan innehålla enums och andra typer.

strukturDjur {
namn: Sträng,
ålder: u8,
animal_type: AnimalType,
}

uppräkningAnimalType {
Katt,
Hund,
Fågel,
// ...
}

De Djur struct innehåller värden för AnimalType uppräkningstyp.

Du kan använda egenskaper för att implementera arv och lägga till beteende till en typ utan att skapa en ny.

dragFlyga {
fnflyga(&själv);
}

Så här kan du implementera Flyga egenskap för flera typer.

strukturFågel {
namn: Sträng,
vingspann: f32,
}

impl Flyga för Fågel {
fnflyga(&själv) {
println!("{} flyger!", själv.namn);
}
}

strukturPlan {
modell: Sträng,
högsta hastighet: u32,
}

impl Flyga för Plan {
fnflyga(&själv) {
println!("{} flyger!", själv.modell);
}
}

De Fågel och Plan structs implementera Flyga egenskap och tryck strängar med Skriv ut! makro.

Du kan ringa till flyga metod på båda strukturerna utan att känna till deras specifika typer.

fnhuvud() {
låta fågel = Fågel {
namn: Sträng::från("Örn"),
vingspann: 2.0,
};

låta plan = Plane {
modell: Sträng::från("Boeing 747"),
högsta hastighet: 900,
};

låta flygande_objekt: Vecdyn Flyga> = vec![&fågel, &plan];

för objekt i flying_objects {
object.fly();
}
}

De huvud funktionen instansierar Plan och Fågel typer. De flygande_objekt vektor är en vektor av objektinstanserna, och för loop går genom vektorn och anropar flyga metod på instanserna.

Implementering av polymorfism i rost

En klass eller typ är polymorf om flera typer representerar ett gränssnitt. Eftersom egenskaper tillhandahåller funktionen för att definiera beteenden i Rust, samtidigt som de tillhandahåller ett gemensamt gränssnitt för att skriva generisk kod, kan du använda egenskaper för att implementera polymorfism.

Här är en egenskap som heter Dragbar som definierar beteendet för att rendera objekt på skärmen:

dragDragbar {
fndra(&själv);
}

Typer som implementerar Drawable-egenskapen kan komma åt dra fungera.

strukturRektangel {
bredd: u32,
höjd: u32,
}

impl Dragbar för rektangel {
fndra(&själv) {
// Rendera rektangeln på skärmen
}
}

Du kan skriva generisk kod som ritar objekt som implementerar Dragbar drag.

fnrita_objekt(objekt: &T) {
object.draw();
}

De rita_objekt funktion tar en generisk typ T som input som implementerar Dragbar egenskap och kallar den dra metod på egenskapen. Olika objekt kan implementera Dragbar egenskap och tillgång till funktionaliteten.

Implementering av abstraktion i rost

Abstraktion är OOP-konceptet där klasser och gränssnitt är tillgängliga för specificerade objekt och typer. Du kan implementera abstraktion i Rust med egenskaper.

Här är ett exempel på egenskap för en mediaspelare:

dragMedia {
fnspela(&själv);
}

Strukturer och uppräkningar som implementerar Media egenskap måste ge en implementering för spela metod.

strukturLåt {
titel: Sträng,
konstnär: Sträng,
}

impl Media för Låt {
fnspela(&själv) {
println!("Spelar låt: {} av {}", själv.titel, själv.konstnär);
}
}

De Låt struct implementerar Media egenskap genom att tillhandahålla en implementering för spela metod som skriver ut ett meddelande med fälten i Låt strukturer till konsolen.

fnhuvud() {
// Skapa en instans av Song-strukturen
låta sång = sång {
titel: Sträng::från("Bohemian Rhapsody"),
konstnär: Sträng::från("Drottning"),
};

// Anropa uppspelningsmetoden på låtinstansen
song.play();
}

De låt variabel är en instans av Låt struct, och variabeln kan komma åt och anropa spela metod.

Att organisera rostkod är enkelt

Objektorienterad programmering hjälper till med kodorganisering. Tack vare Rusts modulsystem kan du enkelt organisera din Rust-kod samtidigt som du implementerar OOP-koncepten för din applikation för att hålla din kod organiserad, hanterbar och intuitiv.