- Rust allows you to define structure types
or structs as they're known.
In a structure, you can define related fields,
and related functionality,
and also you can implement traits.
Remember in Rust, a trait is like an interface.
So, this would be equivalent
to some of the concepts of classes in other languages.
In other languages, like Java and C Sharp, C++ and Python,
you can define classes.
In Rust, they're called structures.
In Rust, we have traits,
in other languages, we have interfaces.
So, the concepts are quite similar in Rust
but the terminology and the syntax is different
probably from what you're gonna be familiar with
in those other languages.
So, to define a structure type,
you use the struct keyword,
you give your structure type a name,
starting with capital letter.
Rust is quite fussy about that.
And then you define the field names and types.
You can also define functionality for structure,
like you could for a class in other languages.
We'll have a look at that in the next lesson.
Right. Here's a simple example.
I've defined a structure type called Employee.
An Employee has a field called name,
which is a string, salary is an unsigned 64.
That's ambitious, isn't it?
And then a fulltime boolean field as well.
I haven't actually created any objects yet,
I've just defined the shape of the structure in memory.
Now, by default, a structure and its fields are private.
You can only access the structure and its fields
within the module, within the file they're defined.
Okay. And that might be fine,
but if you want a structure to be accessed elsewhere,
then you have to marked it as public.
You have to use the pub keyword on the structure type.
You also have to do that with the fields.
If you want the fields to be public,
then you have to say pub on each field as well.
Otherwise, the fields would be private just to that file.
Now, it's quite common to put a structure
into a separate module file, so it can then be reused
across the entire application.
So that's what we are going to do.
In order for that structure to be visible outside that file,
we'd have to make it public.
And I'm gonna do that.
They're gonna have a public structure and public fields,
and I'm gonna put it into a separate file called mytypes.rs.
You can call the file anything you want, okay?
It's not like Java,
where you have to have a file name called employee.java.
You can call it anything you want to,
and you can have as many structure types as you want
in a given file.
So mytypes.rs, it defines a public structure Employee
with public fields.
At the moment, it's just a file.
In order to introduce that file as a module
in your application, then in main.rs,
you'd have to declare it as a module.
Okay? So remember this is important.
We need to declare a module in Rust called mytpes.
It will go and look for a file called mytypes.rs
in the current folder by default.
And it'll drag that code and effectively input that code
into your application.
If you forgot to say mod mytypes,
the compiler would completely ignore this file
and it wouldn't be part of your code base.
So, don't forget to declare the module
to effectively import the code into your application.
So, let's say we've done that.
Let's say, we declared the module mytypes
and I want to actually create an employee object.
Well, you could use fully qualified syntax like this.
We haven't seen the syntax before.
So let me explain.
Effectively in Rust, you have kind of like a module,
a hierarchy, whenever your project might be called,
there's a logical namespace at the top called crate, okay?
That represents the root namespace in your project.
And then for each module, each module or submodule
is considered to be like a child.
So we have a hierarchy of names, mytypes,
and in mytypes, I've defined a structure called Employee.
Okay? So in anywhere in your application,
if you want to use the Employee structure,
you could say effectively crate is a keyword,
go to the root of my namespace,
here, underneath go to the submodule called mytypes,
which is here.
And then in there, you'll find the Employee structure type,
which is there.
So that's a fully qualified syntax.
You could use the syntax anywhere
you wanted to use Employee in your application.
It would get quite tiresome though,
have to say crate, colon, colon,
mytypes, colon, colon, employee.
Simpler approach that people usually go for,
is to use the used statement.
Remember, what the used statement does,
it just brings something into scope, okay?
So the Employee structure type already exists.
All you're doing is introducing it into the current scope.
So, when you say use crate mytypes Employee,
it means you can then use this symbol name
directly in your application rather than
have to use the fully qualified name like we did before.
Okay. Right.
Well, we'll have a look at an example.
For this lesson, the project is
lesson10_structs_getting_started.
Let me just quickly show you that.
All right, so in the rustdev demos folder,
lesson10_structs_getting_started.
So, if you open that project in code editor,
and here we are, the files
that we're going to look at up here are.
Well, first of all mytypes.rs as advertised,
it defines a public structure called Employee
with public fields.
And then in the main code,
I declare it as a module,
technically that's how you'd say it.
I declare it as a module that causes
that file to be processed.
I've got some other modules as well.
Each of these other modules is illustrating
different techniques per section in the lesson.
So, as well as importing the mytypes module
which has got my Employee structure.
I've also imported, for example, demo_accessing_struct.
And that's here.
And in this example,
I've imported from the top level namespace in my crate.
I've imported the mytypes module.
I've imported the Employee structure name.
Okay. I could still use the fully qualified name
if I want to.
I've declared a variable here called e1.
Notice the underscore because I'm not actually
gonna be using the variable just yet.
So, I've got an underscore here
to avoid getting compiler warnings.
Anyway, e1 is off type crate, colon, colon,
mytypes, colon, colon, Employee, right?
So that would've worked, even if I hadn't imported the name.
But since as I have imported the name Employee,
I could just use the employee name directly,
and of course that would be a much better approach.
So, really here I wouldn't bother
using the fully qualified name,
I would just declare that as an Employee as well.
I was just put in there just to remind you.
Wouldn't it be interesting to see
how many bytes an Employee object would take?
Well, in the standard crate, there's the mem module,
which has a size of function, which is generic,
you can give it a type
and it'll tell you how many bytes that type is,
what's the size of that type in bytes.
So, I thought it would be quite interesting to see.
Right. Well, in my main code,
let me just run the demo_accessing_instruct.
That's the code we just saw
and it'll tell us how big the structure type is in memory.
We haven't actually created any instances yet,
but in theory, how big is the structure type itself?
Cargo run.
So, it turns out the size of a structure of an Employee
is 40 bytes.
Okay. So,
a u64 is eight bytes.
A boolean is probably one or two bytes.
A string is probably about 24 bytes, I think.
So, there's pretty some alignment in there,
just to make the fields align nicely.
But anyway, it tells me one of those
will be 40 bytes in size.
So, we've seen how to define structured types,
and basically how to organize it into separate modules.
What we're gonna see in the next demo
is how to actually create employees
and actually start accessing the fields inside them.