
Splitting libraries into multiple files
We have seen the single-file approach to define a library, so now let's explore how to split the library definition into multiple files to allow us to organize the project in small, reusable pieces (which is the real purpose of using libraries).
To define a multiple-file library, we can use the combined part, part of, and library statements:
- part: This allows a library to specify that it's composed of small library parts.
- part of: The small library part specifies which library it helps to compose.
- library: This is for using the preceding part statements, as we need to relate part files with the main part of the library.
Let's examine what the preceding example looks like by using the part statements:
// the 'main' part of the library, person_library.dart
// defined using the library keyword and listing parts below
library person;
part 'person_types.dart';
part 'student.dart';
part 'programmer.dart';
class Person {
String firstName;
String lastName;
PersonType _type;
Person({this.firstName, this.lastName});
String toString() => "($_type): $firstName $lastName";
}
Let's make some observations about the preceding code, as follows:
- The library keyword is followed by the library identifier, person, in this case. It's good practice to name the identifier by using only lowercase characters and the underscore character as a separator. Our example could be called anything such as person_lib or person_library.
- The library parts are listed just below the library definition.
- The code itself does not change anything.
The part syntax is defined as follows:
- The PersonType part is defined in the person_types.dart file:
part of person;
enum PersonType { student, employee }
- The Student part is defined in the student.dart file:
part of person;
class Student extends Person {
Student({firstName, lastName})
: super(firstName: firstName, lastName: lastName) {
_type = PersonType.student;
}
}
- The Programmer part is defined in the programmer.dart file:
part of person;
class Programmer extends Person {
Programmer({firstName, lastName})
: super(firstName: firstName, lastName: lastName) {
_type = PersonType.employee;
}
}
Additionally, as you can see, the _type property is also accessible in the part files, as it's private to the person library and all of the files are in the same library.
Let's take a look at the following code, which uses the person library:
import 'person_lib/person_library.dart';
main() {
// access the Programmer class is allowed, part of the person_library
Programmer programmer = Programmer(firstName: "Dean", lastName: "Pugh");
// cannot access the _type property, it is private to person library
// programmer._type = PersonType.employee;
print(programmer);
}
Take a look at the preceding code; the person library customer does not need to change anything, as the modifications we made are in the library's inner structure.