Rust mangler indbygget støtte til OOP, men du kan bruge disse teknikker til at drage fordel af paradigmet alligevel.

Objektorienteret programmering (OOP) forenkler softwaredesign ved at lægge vægt på brugen af ​​objekter til at repræsentere virkelige enheder og koncepter. OOP tilskynder til vedligeholdelse ved at indkapsle funktionalitet i objekter.

Rust er et fleksibelt sprog, der understøtter funktionel og proceduremæssig programmering. Selvom det ikke understøtter objektorienteret programmering indbygget, kan du implementere OOP-koncepter ved hjælp af Rusts indbyggede datatyper.

Indkapsling i Rust

Indkapsling indebærer organisering af kode i selvstændige enheder, der skjuler interne detaljer, mens eksponere en offentlig grænseflade til ekstern interaktion for at minimere kompleksitet og forbedre kode vedligeholdelse.

Du kan indkapsle Rustkode med moduler. Et modul er en samling af elementer, herunder funktioner, strukturer, enums og konstanter. Rustmoduler giver funktionalitet til at gruppere og definere grænser mellem dele af et program.

instagram viewer

Brug af moduler til at indkapsle data og funktioner

Du kan definere et modul ved hjælp af mod nøgleord efterfulgt af et navn:

mod mit_modul {
// modul elementer gå her
}

Du kan organisere moduler hierarkisk ved at indlejre deres erklæringer:

mod parent_module {
mod mit_modul {
// modul elementer gå her
}
}

Du kan derefter henvise til indlejrede moduler med det fulde hierarki og adskille hvert modul med et dobbelt kolon, f.eks. parent_module:: mit_modul.

Som standard er elementer i moduler private og kun tilgængelige for kode inden for det samme modul. Men du kan gøre moduler offentlige ved hjælp af pub søgeord:

mod mit_modul {
pubfnmin_funktion() {
// function body går her
}
}

Du kan derefter få adgang min_funktion fra andre dele af dit program.

Brug af træk til at definere adfærd

En anden måde, hvorpå Rust muliggør indkapsling, er gennem brugen af ​​egenskaber. Træk definerer adfærd, som typer kan implementere, og sikrer, at forskellige typer passer til den samme grænseflade.

pubegenskabPrintbar {
fnPrint(&selv);
}

pubstrukturMyType {
// struct felter her
}

impl Printbar til MyType {
fnPrint(&selv) {
// implementering her
}
}

Det Printbar egenskab har en Print metode, og MyType struct implementerer Printbar egenskab ved at implementere Print metode.

Ved at bruge egenskaber kan du sikre, at enhver type, der implementerer Printbar egenskab har en Print metode. Dette er praktisk, når du arbejder med generisk kode, der skal fungere sammen med forskellige typer, der deler en fælles adfærd.

Arv i Rust

Nedarvning lader dig definere en klasse baseret på en anden. Underklassen vil arve egenskaberne og metoderne fra sin overordnede.

I Rust opfordres du til at bruge sammensætning i stedet for arv. Komposition er en proces med at skabe nye objekter ved at kombinere eksisterende. I stedet for at oprette en ny klasse, der arver funktionalitet fra basisklassen, kan du oprette en ny struktur, der indeholder en forekomst af basisstrukturen og dens felter.

Oprettelse af nye typer ved at kombinere eksisterende typer

Du skal bruge enums og strukturer til at oprette nye typer. Enums er praktiske for typer med endelige værdier, og strukturer kan indeholde flere felter.

Du kan oprette en enum-type for forskellige typer dyr.

enumDyr {
Kat,
Hund,
Fugl,
// ...
}

Alternativt kan du oprette en struktur, der indeholder felter for hver dyretype. Strukturer kan indeholde enums og andre typer.

strukturDyr {
navn: Snor,
alder: u8,
animal_type: AnimalType,
}

enumAnimalType {
Kat,
Hund,
Fugl,
// ...
}

Det Dyr struct indeholder værdier af AnimalType opregningstype.

Du kan bruge egenskaber til at implementere arv og tilføje adfærd til en type uden at oprette en ny.

egenskabFlyve {
fnflyve(&selv);
}

Her er, hvordan du kan implementere Flyve egenskab for flere typer.

strukturFugl {
navn: Snor,
vingefang: f32,
}

impl Flyve til Fugl {
fnflyve(&selv) {
println!("{} flyver!", selv.navn);
}
}

strukturFly {
model: Snor,
højeste hastighed: u32,
}

impl Flyve til Fly {
fnflyve(&selv) {
println!("{} flyver!", selv.model);
}
}

Det Fugl og Fly structs implementere Flyve egenskab og print strenge med Udskriv! makro.

Du kan ringe til flyve metode på begge strukturer uden at kende deres specifikke typer.

fnvigtigste() {
lade fugl = Fugl {
navn: Snor::fra("Ørn"),
vingefang: 2.0,
};

lade fly = Plane {
model: Snor::fra("Boeing 747"),
højeste hastighed: 900,
};

lade flyvende_objekter: Vecdyn Flyv> = vec![&fugl, &fly];

til objekt i flyvende_objekter {
object.fly();
}
}

Det vigtigste funktion instansierer Fly og Fugl typer. Det flyvende_objekter vektor er en vektor af objektforekomsterne, og til sløjfe krydser vektoren og kalder flyve metode på instanserne.

Implementering af polymorfi i rust

En klasse eller type er polymorf, hvis flere typer repræsenterer en grænseflade. Da træk giver funktionaliteten til at definere adfærd i Rust, mens de giver en fælles grænseflade til at skrive generisk kode, kan du bruge træk til at implementere polymorfi.

Her er et træk navngivet Tegnbar der definerer adfærden for gengivelse af objekter på skærmen:

egenskabTegnbar {
fntegne(&selv);
}

Typer, der implementerer Drawable-egenskaben, kan få adgang til tegne fungere.

strukturRektangel {
bredde: u32,
højde: u32,
}

impl Tegnbar til Rektangel {
fntegne(&selv) {
// Gengiv rektanglet på skærmen
}
}

Du kan skrive generisk kode, der tegner objekter, der implementerer Tegnbar egenskab.

fntegne_objekt(objekt: &T) {
objekt.tegne();
}

Det tegne_objekt funktion tager en generisk type T som input, der implementerer Tegnbar egenskab og kalder den tegne metode på egenskaben. Forskellige objekter kan implementere Tegnbar egenskab og adgang til funktionaliteten.

Implementering af abstraktion i rust

Abstraktion er OOP koncept hvor klasser og grænseflader er tilgængelige for specificerede objekter og typer. Du kan implementere abstraktion i Rust med træk.

Her er et eksempel på en medieafspiller:

egenskabMedier {
fnSpil(&selv);
}

Strukturer og optegnelser, der implementerer Medier egenskab skal give en implementering for Spil metode.

strukturSang {
titel: Snor,
kunstner: Snor,
}

impl Medier til Sang {
fnSpil(&selv) {
println!("Afspiller sang: {} af {}", selv.titel, selv.kunstner);
}
}

Det Sang struct implementerer Medier egenskab ved at give en implementering for Spil metode, der udskriver en besked med felterne i Sang strukturer til konsollen.

fnvigtigste() {
// Opret en instans af sangstrukturen
lade sang = Sang {
titel: Snor::fra("Bohemian Rhapsody"),
kunstner: Snor::fra("Dronning"),
};

// Kald afspilningsmetoden på sangforekomsten
sang.afspil();
}

Det sang variabel er en forekomst af Sang struct, og variablen kan få adgang til og kalde Spil metode.

Det er nemt at organisere rustkode

Objektorienteret programmering hjælper med kodeorganisering. Takket være Rusts modulsystem kan du nemt organisere din Rust-kode, mens du implementerer OOP-koncepterne til din applikation for at holde din kode organiseret, overskuelig og intuitiv.