0Pricing
Learn Rust Coding · Lekcja

Wywołanie statyczne a dynamiczne

Kompromisy

Wywołanie statyczne a dynamiczne to bezpłatna lekcja Learn Rust Coding na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Learn Rust Coding, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.

Dwa sposoby wywoływania

Gdy wywołujesz metodę traitu, Rust musi ustalić, która konkretna implementacja zostanie uruchomiona. Istnieją dwie strategie: statyczne wywołanie (ustalane w czasie kompilacji) oraz dynamiczne wywołanie (ustalane w czasie działania).

Statyczne wywołanie z typami generycznymi

Funkcje generyczne używają statycznego wywołania. Kompilator generuje wyspecjalizowaną kopię dla każdego konkretnego typu — proces ten nazywa się monomorfizacją.

trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }

fn print_area<T: Area>(shape: &T) {
    println!("{}", shape.area());
}

fn main() {
    print_area(&Square { s: 4.0 });
}

Monomorfizacja

Dla każdego typu, z którym wywołujesz funkcję, kompilator tworzy jej dedykowaną wersję. Wywołanie metody staje się bezpośrednim wywołaniem bez wyszukiwania, więc jest równie szybkie jak kod napisany ręcznie.

Dynamiczne wywołanie z dyn

Obiekty traitów używają dynamicznego wywołania. Jedna funkcja obsługuje wszystkie typy, a adres metody jest znajdowany w czasie działania za pomocą vtable.

trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }

fn print_area(shape: &dyn Area) {
    println!("{}", shape.area());
}

fn main() {
    print_area(&Square { s: 4.0 });
}

Vtable

Obiekt traitu jest grubym wskaźnikiem: jedna jego część wskazuje dane, a druga — vtable zawierającą adresy metod. Każde wywołanie odwołuje się do odpowiedniej pozycji w tej tabeli.

Kompromis dotyczący szybkości

Statyczne wywołanie jest szybsze przy każdym wywołaniu i może być rozwijane przez kompilator, ale generuje więcej kodu maszynowego. Dynamiczne wywołanie dodaje niewielkie pośrednie odwołanie, lecz utrzymuje mały rozmiar kodu.

W większości aplikacji różnica jest pomijalna — wybór zależy od potrzebnej elastyczności.

Kompromis dotyczący rozmiaru kodu

Wywoływanie funkcji generycznej z wieloma typami tworzy wiele kopii, co może powiększać plik binarny. Pojedyncza funkcja dyn pozwala uniknąć tego powielania.

Dlatego biblioteki czasami wewnętrznie preferują obiekty traitów.

Kompromis dotyczący elastyczności

Typy generyczne wymuszają jeden konkretny typ w każdym miejscu wywołania, więc nie mogą przechowywać mieszanych typów w kolekcji. Obiekty traitów mogą to robić. Jeśli potrzebujesz heterogenicznej listy, rozwiązaniem jest dynamiczne wywołanie.

trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
struct Rect { w: f64, h: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }
impl Area for Rect { fn area(&self) -> f64 { self.w * self.h } }

fn main() {
    let shapes: Vec<Box<dyn Area>> = vec![Box::new(Square { s: 2.0 }), Box::new(Rect { w: 3.0, h: 4.0 })];
    let total: f64 = shapes.iter().map(|s| s.area()).sum();
    println!("{}", total);
}

Łączenie obu podejść

Można je łączyć: funkcja generyczna może przyjmować na granicy impl Trait, a wewnętrznie przechowywać wartości jako Box<dyn Trait>. Każdego podejścia używaj tam, gdzie najlepiej pasuje.

Wskazówki dotyczące wyboru

Szybkie zasady:

  • Jeden typ na wywołanie, ścieżka krytyczna pod względem wydajności? Użyj typów generycznych (statycznie).
  • Mieszane typy w kolekcji? Użyj dyn (dynamicznie).
  • Obawiasz się rozmiaru pliku binarnego? Skłaniaj się ku dyn.

Oba podejścia nie generują kosztów tam, gdzie ma to znaczenie

Rust nigdy nie dodaje narzutu, o który nie prosisz. Typy generyczne nie generują kosztu w czasie działania, a obiekty traitów kosztują tylko jedno pośrednie odwołanie za pomocą wskaźnika. To Ty jawnie wybierasz kompromis.

Szybki sprawdzian

Sprawdź swoją wiedzę o sposobach wywoływania.

Podsumowanie

Porównano dwa style wywoływania:

  • Statyczne (typy generyczne): monomorfizowane, szybkie, większy plik binarny, jeden typ na wywołanie
  • Dynamiczne (dyn): wyszukiwanie w vtable, elastyczne, mniejszy kod, umożliwia mieszane kolekcje
  • Wybieraj na podstawie potrzeb dotyczących elastyczności, wydajności i rozmiaru pliku binarnego

Często zadawane pytania

Czy lekcja „Wywołanie statyczne a dynamiczne” jest bezpłatna?

Tak — pełny tekst „Wywołanie statyczne a dynamiczne” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Learn Rust Coding, przejdź na CoddyKit PRO. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.

Co nauczysz się w „Wywołanie statyczne a dynamiczne”?

Kompromisy Ćwiczysz Learn Rust Coding z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Learn Rust Coding?

Nie wymagamy żadnego doświadczenia. Learn Rust Coding w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Wywołanie statyczne a dynamiczne”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Learn Rust Coding?

Tak. Każda lekcja Learn Rust Coding zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Definiowanie cech
  2. Obiekty cech i dyn
  3. Wywołanie statyczne a dynamiczne
  4. Metody domyślne
← Powrót do Learn Rust Coding