2016-02-11 13 views
6

Chcę podzielić program Rust na wiele plików, ale użycie mod nie pozwala mi odwoływać się do plików w tym samym katalogu z plików innych niż main.rs.Czy mogę dołączyć moduły "na boki" w Rust?

Na przykład, jeśli mają main.rs, game.rs i matrix.rs w jednym katalogu, to może odwoływać elemencie/funkcji z game.rs lub matrix.rs w main.rs z mod game; lub mod matrix;. Nie mogę jednak odnieść się do matrix.rs z game.rs z instrukcją taką jak mod matrix.

Przyjrzałem się kilku zasobom, a wszystkie mają tylko struktury modułów, takie jak drzewa, które się nie nawzajem odwołują. Czy możliwe jest użycie struktur/funkcji z plików w sobie nawzajem w Rust, czy to wbrew zasadom? Jeśli tak, dlaczego Rust nie pozwala ci tego zrobić?

+0

Spójrz na [tę odpowiedź] (http://stackoverflow.com/a/22597760/994206). Jest to również omówione w [samouczek] (http://static.rust-lang.org/doc/master/book/crates-and-modules.html) – Mokosha

Odpowiedz

11

mod to deklaracja modułu. Niniejsza dyrektywa deklaruje moduł i całą jego zawartość. Tak się składa, że ​​te treści mogą znajdować się w innym pliku. Więc tak:

mod game; 
mod matrix; 

odpowiada w przybliżeniu następująco:

mod game { 
    // game.rs contents 
} 

mod matrix { 
    // matrix.rs contents 
} 

Naturalnie, ponieważ mod jest deklaracja modułu, nie można zrobić to kilka razy do tego samego modułu. Oznacza to, że można spróbować i napisać coś podobnego

mod game { 
    mod matrix; 
    ... 
} 

mod matrix; 

ale, jak widać, matrix i game::matrix są różne moduły i naturalnie rustc wymaga różne ścieżki do swoich plików, jeśli są zewnętrzne.

use, jednakże jest to deklaracja importu. use deklaracje pobierają nazwy z innych modułów do wykorzystania w bieżącym module. Z dowolnego miejsca tego modułu można korzystać z dowolnego modułu i dowolnych publicznych elementów z dowolnej liczby razy.

Tak, aby odwoływać matrix z game trzeba go use:

// game.rs 
use matrix; 

Oczywiście, aby to zadziałało matrix powinny zostać uznane ze mod w korzeniu skrzyni.

Osobiście uważam, że najprostszym sposobem zrozumienia systemu modułów Rust jest zapominanie, że moduły można w ogóle umieścić w różnych plikach. Oznacza to, że jakaś skrzynia może być zdefiniowana tylko w jednym pliku. Rust mod dyrektyw może mieć ciała i może gniazdo, tak zagnieżdżone mod s faktycznie zdefiniować system moduł skrzyni:

mod foo { 
    mod bax { 
     ... 
    } 
    mod baz { 
     ... 
    } 
} 
mod bar { 
    mod qux { 
     mod zux { 
      ... 
     } 
    } 
} 

Jeśli masz tylko jeden plik, można łatwo zobaczyć, jak mod i use dyrektyw będzie działać , a związek między modułami powinien stać się jasny.

A teraz tylko trzeba dodać do obrazu fakt, że jeśli moduł jest zadeklarowana bez ciała, jak w mod name;, jego zawartość jest załadowany albo z name.rs lub name/mod.rs, co jest dostępne. Jednak pełny obraz nie zmienia się w najmniejszym stopniu - nadal są to moduły zagnieżdżone, które mogą być zawsze reprezentowane jako pojedynczy plik źródłowy z zagnieżdżonymi dyrektywami mod. W rzeczywistości, cargo rustc -Z unstable-options --pretty=normal wydrukuje twoją skrzynię w tym formularzu, po tym jak wszystkie moduły w zewnętrznych plikach źródłowych zostaną połączone w jeden dokument. Sugeruję uruchomienie tego polecenia na niektórych skrzyniach z rozbudowaną strukturą modułów, aby zobaczyć, jak to wygląda w praktyce.

+0

Dla mnie zrozumienie mod jest równoważne C lub Cpp #include dyrektywy z niektórymi funkcjami wyszukiwania, aby wyszukać nazwę/mod lub name.rs, ale mogłem pominąć subtelności. –

+4

@XavierT. dwie główne różnice między C/C++ i Rustem to po pierwsze, że jednostka kompilacji w Rust jest znacznie większa niż w C/C++ (skrzynia, która odpowiada jednemu lub kilku plikom .rs i jednemu lub więcej modułów, w porównaniu do plik obiektowy, który odpowiada dokładnie jednemu plikowi .c/.cpp z tekstowo włączonymi nagłówkami), a po drugie, że w modułach Rust rzeczywiście udostępniają przestrzenie nazw i enkapsulacji, co nie jest prawdą dla C i jest tylko częściowo prawdziwe dla C++ (gdzie przestrzenie nazw istnieją , ale nie są powiązane z jednostkami kompilującymi i nie zapewniają granic abstrakcji). –

+0

Ach tak, przestrzeń nazw jest również ważna! –

Powiązane problemy