Newtype-suunnittelumalli
Käärikää tyyppejä turvallisuuden ja selkeyden vuoksi.
Newtype-suunnittelumalli on ilmainen Rust-ohjelmoinnin perusteet-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Rust-ohjelmoinnin perusteet-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Rust-ohjelmoinnin perusteet-kurssilla on yhteensä 4 oppituntia.
Mikä on newtype?
Newtype on yhden kentän tuple-rakenne, joka käärii olemassa olevan tyypin ja antaa sille erillisen identiteetin. struct Meters(f64) on täysin uusi tyyppi, vaikka se sisältää tavallisen f64-arvon.
Kääre ei aiheuta ajonaikaista kustannusta, mutta sen avulla kääntäjä voi valvoa merkityksiä, joita raaka perustyyppi ei pysty ilmaisemaan.
struct Meters(f64);
struct Seconds(f64);Yksiköiden sekoittumisen estäminen
Raakoja perustyyppejä on helppo sekoittaa keskenään. Jos sekä etäisyys että aika ovat f64-tyyppisiä, mikään ei estä vaihtamasta niitä keskenään kutsussa.
Kunkin arvon kääriminen omaan newtype-tyyppiinsä muuttaa tällaiset virheet käännösaikaisiksi virheiksi hiljaisten bugien sijaan.
fn speed(d: Meters, t: Seconds) -> f64 {
d.0 / t.0
}
// speed(Seconds(2.0), Meters(10.0)) -> compile errorSisäiseen arvoon käsiksi pääseminen
Käärittyyn arvoon pääsee tuple-indeksillä .0. Monet newtype-tyypit tarjoavat myös metodin tai toteuttavat From-traitin sujuvia muunnoksia varten.
struct UserId(u64);
impl UserId {
fn value(&self) -> u64 { self.0 }
}
fn main() {
let id = UserId(42);
println!("id = {}", id.value());
}Invarianttien kapselointi
Tehkää sisäisestä kentästä yksityinen ja tarkistakaa arvo konstruktorissa. Tällöin jokainen newtype-tyypin arvo on varmasti kelvollinen, eikä sitä tarvitse tarkistaa uudelleen muualla koodissa.
pub struct Email(String);
impl Email {
pub fn new(s: &str) -> Option<Email> {
if s.contains('@') {
Some(Email(s.to_string()))
} else {
None
}
}
}Orposääntö
Rust kieltää vieraan traitin toteuttamisen vieraalle tyypille. Ette voi kirjoittaa impl Display for Vec<T>, koska ette omista traitia ettekä tyyppiä.
Tämä sääntö pitää traitien yhteensopivuuden eheänä eri cratejen välillä, mutta voi estää hyödyllisiä toteutuksia.
Newtype-tyypit kiertävät orposäännön
Koska newtype on määritelty omassa cratessanne, omistatte nyt paikallisen tyypin ja voitte toteuttaa sille minkä tahansa traitin. Tämä on tavallinen kiertotapa orphan-säännölle.
use std::fmt;
struct Wrapper(Vec<String>);
impl fmt::Display for Wrapper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}Suoritettava Wrapper Display
Tässä edellisen kohtauksen wrapper otetaan käyttöön. Omistatte Wrapper-tyypin, joten Display-traitin toteuttaminen sille on sallittua, ja ohjelma tulostaa yhdistetyn listan.
use std::fmt;
struct Wrapper(Vec<String>);
impl fmt::Display for Wrapper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}
fn main() {
let w = Wrapper(vec!["a".into(), "b".into()]);
println!("{}", w);
}Rajapinnan rajoittaminen
Tehokkaan tyypin kääriminen antaa teille mahdollisuuden tarjota vain turvallisen osajoukon sen toiminnallisuudesta. NonEmptyVec voi piilottaa muokkaavat metodit, jotka mahdollistaisivat sen muuttumisen tyhjäksi, ja säilyttää näin invarianttinsa.
pub struct NonEmptyVec<T>(Vec<T>);
impl<T> NonEmptyVec<T> {
pub fn new(first: T) -> Self {
NonEmptyVec(vec![first])
}
pub fn first(&self) -> &T {
&self.0[0]
}
}Kustannukseton abstraktio
Yhden kentän sisältävällä newtypellä on sama muistiasettelu kuin käärityllä arvolla. Kääntäjä optimoi wrapperin pois, joten turvallisuudesta ei tässä tapauksessa todellakaan aiheudu ajonaikaisia kustannuksia.
#[repr(transparent)]-määritteen lisääminen takaa samanlaisen muistiasettelun, mikä on tärkeää FFI:n yhteydessä.
#[repr(transparent)]
struct Celsius(f64);Traitien johdattaminen newtypeille
Newtypeille johdatetaan usein standarditraiteja, jotta ne käyttäytyvät tarvittaessa sisemmän arvon tavoin. Johdattaminen tekee niistä käteviä avaimina, vertailuissa ja debug-tulosteissa.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct ProductId(u32);
fn main() {
let a = ProductId(7);
let b = a.clone();
println!("{:?} == {:?}: {}", a, b, a == b);
}Newtype ja type alias
Älkää sekoittako newtypea type aliakseen. type Meters = f64 on vain nimi; kyseessä on edelleen f64, eikä se lisää turvallisuutta.
Newtype struct Meters(f64) on aidosti erillinen tyyppi, jonka kääntäjä voi pitää erillään.
type Km = f64; // alias: interchangeable with f64
struct Mi(f64); // newtype: distinct from f64Pikatarkistus
Päättäkää, miksi newtype auttaa tilanteessa, jossa type alias ei auta.
Kertaus
Newtype-kuvio käärii olemassa olevan tyypin yhden kentän tuple structiin, jotta sille saadaan erillinen identiteetti ilman ajonaikaisia kustannuksia. Se estää arvojen sekoittumista, kapseloi invariantit yksityisen kentän taakse ja kiertää orphan-säännön, joten voitte toteuttaa vieraita traitteja.
Toisin kuin type alias, newtype on todellinen, erillinen tyyppi.
Opi Rust tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 39
- Oppitunnit
- 144
Usein kysytyt kysymykset
Onko oppitunti ”Newtype-suunnittelumalli” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Rust-ohjelmoinnin perusteet-oppimispolun 3 oppituntia, myös oppitunnin “Newtype-suunnittelumalli”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Rust-ohjelmoinnin perusteet-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Newtype-suunnittelumalli”?
Käärikää tyyppejä turvallisuuden ja selkeyden vuoksi. Harjoittelet Rust-ohjelmoinnin perusteet-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Rust-ohjelmoinnin perusteet-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Rust-ohjelmoinnin perusteet-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.
Kuinka kauan ”Newtype-suunnittelumalli”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Rust-ohjelmoinnin perusteet-oppitunnilla?
Kyllä. Jokainen Rust-ohjelmoinnin perusteet-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Builder-suunnittelumalli
- Newtype-suunnittelumalli
- Tyyppitilaan perustuvat builderit
- Deref ja wrapperien ergonomia