1 00:00:06,630 --> 00:00:08,820 - A Trait in Rust is similar to an interface 2 00:00:08,820 --> 00:00:10,740 in other object-oriented languages. 3 00:00:10,740 --> 00:00:12,030 When you define a trait, 4 00:00:12,030 --> 00:00:14,610 the trait can define abstract methods. 5 00:00:14,610 --> 00:00:17,487 Methods that must be overridden by a structure. 6 00:00:17,487 --> 00:00:19,500 You can also define default methods. 7 00:00:19,500 --> 00:00:21,510 So these methods can be overridden, 8 00:00:21,510 --> 00:00:22,530 but they don't have to be. 9 00:00:22,530 --> 00:00:25,110 They have a default implementation to fall back on. 10 00:00:25,110 --> 00:00:27,450 Many object-oriented languages are providing 11 00:00:27,450 --> 00:00:32,040 this kind of default method mechanism these days. 12 00:00:32,040 --> 00:00:35,310 A trait can also define constants, okay? 13 00:00:35,310 --> 00:00:37,350 And constants can be overridden. 14 00:00:37,350 --> 00:00:38,490 And in a structure, 15 00:00:38,490 --> 00:00:41,370 we'll have a look at all these details later on. 16 00:00:41,370 --> 00:00:43,680 First of all, here's a simple example of a trait. 17 00:00:43,680 --> 00:00:45,720 I've find a trait called Print. 18 00:00:45,720 --> 00:00:49,110 The trait name is usually has a capital letter 19 00:00:49,110 --> 00:00:50,970 and it can have methods. 20 00:00:50,970 --> 00:00:54,630 This trait has a single method called print 21 00:00:54,630 --> 00:00:57,360 which must be implemented by a structure 22 00:00:57,360 --> 00:01:00,900 to print the object that you specify. 23 00:01:00,900 --> 00:01:02,640 So, couple of things to note. 24 00:01:02,640 --> 00:01:05,760 All members in a trade are implicitly public, 25 00:01:05,760 --> 00:01:08,340 you can't actually use the pub key with here. 26 00:01:08,340 --> 00:01:11,223 It's public by default and it must be public. 27 00:01:12,210 --> 00:01:13,950 Right, well, here's an example. 28 00:01:13,950 --> 00:01:16,230 This looks a bit different from what you might expect. 29 00:01:16,230 --> 00:01:18,720 I've got a structure called Employee. 30 00:01:18,720 --> 00:01:20,700 I've defined the data of the structure here. 31 00:01:20,700 --> 00:01:24,210 An Employee has a name, and a salary, and a full-time state. 32 00:01:24,210 --> 00:01:27,630 I've defined the regular implementation for an employee, 33 00:01:27,630 --> 00:01:30,870 like payrise and two string and such like. 34 00:01:30,870 --> 00:01:34,950 But your implementation also has a separate section 35 00:01:34,950 --> 00:01:37,890 as well as the regular methods for employee. 36 00:01:37,890 --> 00:01:39,630 You've also got the bit which implements 37 00:01:39,630 --> 00:01:42,600 the print interface for employee. 38 00:01:42,600 --> 00:01:43,433 All right? 39 00:01:43,433 --> 00:01:46,890 So, for each interface of each trait that you implement, 40 00:01:46,890 --> 00:01:48,870 you have a separate block like this. 41 00:01:48,870 --> 00:01:53,870 This is the implementation of the Print trait for Employee. 42 00:01:54,510 --> 00:01:56,520 In other words, here is the print function, 43 00:01:56,520 --> 00:02:00,600 if the Employee implements the Print trait 44 00:02:00,600 --> 00:02:02,130 then here's the print function 45 00:02:02,130 --> 00:02:05,943 and self here will be the employee. 46 00:02:06,900 --> 00:02:09,840 So, it'll print out the employee's name, 47 00:02:09,840 --> 00:02:11,430 and the employee's salary 48 00:02:11,430 --> 00:02:14,760 and the employee's full-time status. 49 00:02:14,760 --> 00:02:15,810 Okay? 50 00:02:15,810 --> 00:02:18,420 So rather than put in the print function in here, 51 00:02:18,420 --> 00:02:20,100 which is what you might've expected, 52 00:02:20,100 --> 00:02:21,840 you put it into an explicit block. 53 00:02:21,840 --> 00:02:24,900 This is explicitly the implementation block 54 00:02:24,900 --> 00:02:28,443 where we implement that trait for this employee structure. 55 00:02:30,060 --> 00:02:33,000 Right? So you can imagine that by the time 56 00:02:33,000 --> 00:02:34,440 you defined all your traits 57 00:02:34,440 --> 00:02:36,961 and then all the structures which implement those traits, 58 00:02:36,961 --> 00:02:39,750 you're gonna have quite a lot of files involved. 59 00:02:39,750 --> 00:02:41,520 So you have to think carefully about 60 00:02:41,520 --> 00:02:43,890 how you're gonna organize that into modules 61 00:02:43,890 --> 00:02:45,060 in your vast project. 62 00:02:45,060 --> 00:02:48,090 So, what we've decided to do in this demo 63 00:02:48,090 --> 00:02:49,800 is to have separate modules. 64 00:02:49,800 --> 00:02:51,990 I've got a module called mytraits, 65 00:02:51,990 --> 00:02:54,000 which we define all the traits. 66 00:02:54,000 --> 00:02:56,520 I've got a separate module called mystructs, 67 00:02:56,520 --> 00:02:58,110 which will define all the structures 68 00:02:58,110 --> 00:02:59,550 which implement those traits. 69 00:02:59,550 --> 00:03:01,920 So there'll be two separate directory structures, 70 00:03:01,920 --> 00:03:04,860 a directory structure where all my traits live, 71 00:03:04,860 --> 00:03:06,600 and a separate directory structure 72 00:03:06,600 --> 00:03:10,560 where all my structures live which implement those traits. 73 00:03:10,560 --> 00:03:12,360 Kind of made sense to me. 74 00:03:12,360 --> 00:03:15,120 So, this is how it's going to look diagrammatically. 75 00:03:15,120 --> 00:03:17,520 So, in my project at the top level, 76 00:03:17,520 --> 00:03:19,920 I have my crate root directory, 77 00:03:19,920 --> 00:03:22,980 and in there I've got main.rs. 78 00:03:22,980 --> 00:03:26,973 And in main.rs, I define a module called mytraits. 79 00:03:28,056 --> 00:03:31,380 Okay? And when you define a module called mytraits, 80 00:03:31,380 --> 00:03:35,460 you must then have a file called mytraits.rs, 81 00:03:35,460 --> 00:03:38,190 and I could have defined mytraits directly in here 82 00:03:38,190 --> 00:03:40,470 or I can push it down into a subdirectory. 83 00:03:40,470 --> 00:03:43,350 Remember, we saw this in the previous lesson, 84 00:03:43,350 --> 00:03:45,960 you can either define everything in one file 85 00:03:45,960 --> 00:03:48,270 or you can push it into a subdirectory 86 00:03:48,270 --> 00:03:50,550 and define it as a submodule. 87 00:03:50,550 --> 00:03:55,533 So, in mytraits.rs, I define a submodule called print, 88 00:03:57,060 --> 00:04:00,840 which therefore implies a file called print.rs 89 00:04:00,840 --> 00:04:02,580 in the mytraits folder. 90 00:04:02,580 --> 00:04:05,580 So, let me just remind you how this works. 91 00:04:05,580 --> 00:04:09,630 In a file which represents a module, 92 00:04:09,630 --> 00:04:12,180 if you define a submodule, 93 00:04:12,180 --> 00:04:15,810 then if the file is called mytraits.rs, 94 00:04:15,810 --> 00:04:19,620 it will look in a subfolder with the same name, mytraits. 95 00:04:19,620 --> 00:04:23,340 And in there, it'll look for a file called print.rs. 96 00:04:23,340 --> 00:04:26,340 And in there, I define the Print trait, 97 00:04:26,340 --> 00:04:29,820 I could also have other traits defined as well. 98 00:04:29,820 --> 00:04:34,800 For example, I could define a public module called loggable, 99 00:04:34,800 --> 00:04:36,780 and I could have a loggable.rs, 100 00:04:36,780 --> 00:04:39,150 which defines my loggable trait. 101 00:04:39,150 --> 00:04:42,150 Okay? So I'll define one trait per file, 102 00:04:42,150 --> 00:04:45,270 and I'll have lots of files organized into a subfolder. 103 00:04:45,270 --> 00:04:48,870 So, mytraits.rs and mytraits the folder 104 00:04:48,870 --> 00:04:51,030 will define all of my traits. 105 00:04:51,030 --> 00:04:53,640 And then back up at the top level, 106 00:04:53,640 --> 00:04:56,647 I've also declared a module called mystructs. 107 00:04:56,647 --> 00:05:00,300 Okay? And I have a file called mystructs.rs 108 00:05:00,300 --> 00:05:02,400 and a folder called mystructs. 109 00:05:02,400 --> 00:05:05,160 And in mystructs.rs, I define submodules, 110 00:05:05,160 --> 00:05:07,500 for example, employee, okay? 111 00:05:07,500 --> 00:05:09,870 So, if you in mystructs.rs 112 00:05:09,870 --> 00:05:12,090 and you define a module called employee, 113 00:05:12,090 --> 00:05:16,140 then the compiler will look in the folder called mystructs, 114 00:05:16,140 --> 00:05:19,770 for a file called employee.rs 115 00:05:19,770 --> 00:05:22,560 where you define your employee structure. 116 00:05:22,560 --> 00:05:26,070 So, you have to be quite careful, you have to think, 117 00:05:26,070 --> 00:05:28,950 you have to plan basically your directory structure, 118 00:05:28,950 --> 00:05:32,620 and organize your work into separate modules 119 00:05:34,014 --> 00:05:36,300 and submodules, and give it some thought 120 00:05:36,300 --> 00:05:38,190 because it's quite different from the way 121 00:05:38,190 --> 00:05:40,563 application structures work in other languages. 122 00:05:41,880 --> 00:05:45,180 So, how about using those structures and those traits 123 00:05:45,180 --> 00:05:46,830 in your client code? 124 00:05:46,830 --> 00:05:49,350 You're gonna have to have some used statements 125 00:05:49,350 --> 00:05:52,140 to import names into scope. 126 00:05:52,140 --> 00:05:54,150 It's gonna look something like this, 127 00:05:54,150 --> 00:05:56,490 in some code in your application, 128 00:05:56,490 --> 00:05:59,760 you would say like, go to the top level in my crate 129 00:05:59,760 --> 00:06:03,090 input into scope the mytraits module, 130 00:06:03,090 --> 00:06:05,070 which has a print submodule, 131 00:06:05,070 --> 00:06:06,903 which defines a trait called Print. 132 00:06:07,830 --> 00:06:11,010 And also, from the top level in my crate, in my project 133 00:06:11,010 --> 00:06:13,080 there's a module called mystructs, 134 00:06:13,080 --> 00:06:15,420 which defines a submodule called employee. 135 00:06:15,420 --> 00:06:18,390 And in that submodule, there's a structure called Employee 136 00:06:18,390 --> 00:06:19,410 with a capital. 137 00:06:19,410 --> 00:06:23,010 Remember that modules as well as being a directory structure 138 00:06:23,010 --> 00:06:27,210 are also kind of like namespaces in rust as well. 139 00:06:27,210 --> 00:06:30,150 So anyway, I've introduced my Employee structure. 140 00:06:30,150 --> 00:06:32,820 I can create an Employee, I can call payrise, 141 00:06:32,820 --> 00:06:34,380 I can also call the print function 142 00:06:34,380 --> 00:06:37,620 because obviously you might implements the print interface 143 00:06:37,620 --> 00:06:38,943 or the Print trait. 144 00:06:39,930 --> 00:06:42,810 Just one word of caution, 145 00:06:42,810 --> 00:06:46,890 if you invoke a method which is defined in a trait, 146 00:06:46,890 --> 00:06:49,800 then you must also import that trait. 147 00:06:49,800 --> 00:06:52,020 So, if I call the print function, 148 00:06:52,020 --> 00:06:55,290 the print function was defined in this trait here, 149 00:06:55,290 --> 00:06:58,110 you have to import the Print trait 150 00:06:58,110 --> 00:07:01,053 in order to invoke a method defined in that trait. 151 00:07:01,890 --> 00:07:06,890 If I'd forgotten to import the Print trait here, 152 00:07:07,800 --> 00:07:10,350 then you get an error message when you try 153 00:07:10,350 --> 00:07:12,600 to invoke a method defined in that trait. 154 00:07:12,600 --> 00:07:15,960 Okay? So that's a bit surprising maybe, 155 00:07:15,960 --> 00:07:18,010 but you'll soon get used to that as well. 156 00:07:19,050 --> 00:07:22,290 Right, so in the example for this chapter, 157 00:07:22,290 --> 00:07:24,183 this is the project lesson12_traits. 158 00:07:25,530 --> 00:07:27,210 And if you look in that project 159 00:07:27,210 --> 00:07:29,460 we'll have a look at there in a moment. 160 00:07:29,460 --> 00:07:33,960 So, everything starts at the root level in main.rs 161 00:07:33,960 --> 00:07:36,684 and in there I define submodules 162 00:07:36,684 --> 00:07:40,110 called mytraits and mystructs. 163 00:07:40,110 --> 00:07:42,780 So, we'll have a look at mytraits.rs 164 00:07:42,780 --> 00:07:46,650 and we'll see that it defines a submodule called print 165 00:07:46,650 --> 00:07:48,843 which defines my Print trait. 166 00:07:49,710 --> 00:07:51,390 And then we also define a submodule 167 00:07:51,390 --> 00:07:54,450 called mystructs/employee, 168 00:07:54,450 --> 00:07:56,160 which defines the employee structure, 169 00:07:56,160 --> 00:07:58,020 employee implements print, 170 00:07:58,020 --> 00:07:59,640 and then we'll have the demo code 171 00:07:59,640 --> 00:08:01,710 which actually makes use of these types. 172 00:08:01,710 --> 00:08:03,760 And then we run the application as usual. 173 00:08:04,620 --> 00:08:05,970 Okay, so here we are then. 174 00:08:05,970 --> 00:08:10,970 From the top level notice, I've got a mystructs folder, 175 00:08:10,980 --> 00:08:13,170 I'm gonna have lots of different structures. 176 00:08:13,170 --> 00:08:16,050 You can see now why I've organized it into subdirectories 177 00:08:16,050 --> 00:08:18,390 because there's a lot of stuff here now. 178 00:08:18,390 --> 00:08:19,950 I'm gonna have several traits as well. 179 00:08:19,950 --> 00:08:22,563 We're gonna look at over the next two demos. 180 00:08:23,640 --> 00:08:26,520 Right. So from the top main, 181 00:08:26,520 --> 00:08:30,483 I introduce a module called mytraits. 182 00:08:32,070 --> 00:08:34,120 So, the compiler will look in mytraits.rs 183 00:08:35,610 --> 00:08:38,970 and it'd look for a submodule called log, 184 00:08:38,970 --> 00:08:42,690 and a submodule called print, and a submodule collection. 185 00:08:42,690 --> 00:08:45,036 And it'll looked for those in the mytraits folder. 186 00:08:45,036 --> 00:08:48,480 So, in the mytraits folder, it look for a log.rs, 187 00:08:48,480 --> 00:08:51,933 a print.rs, and a collections.rs, 188 00:08:52,980 --> 00:08:53,930 and there they are. 189 00:08:54,810 --> 00:08:57,390 Print.rs, is the one of interest for us at the moment. 190 00:08:57,390 --> 00:09:00,540 In there, we define our public Print trait 191 00:09:00,540 --> 00:09:03,483 with the print method to be implemented. 192 00:09:04,710 --> 00:09:06,420 Okay, back to main. 193 00:09:06,420 --> 00:09:11,400 I've also defined a module called mystructs, okay? 194 00:09:11,400 --> 00:09:16,400 And mystructs is here and it defines 195 00:09:16,740 --> 00:09:21,390 various different submodules, employee, point, and so on. 196 00:09:21,390 --> 00:09:25,410 Employee is the first submodule and it look for, 197 00:09:25,410 --> 00:09:28,710 if we're currently in mystructs.rs, 198 00:09:28,710 --> 00:09:30,810 it look in the mystructs folder 199 00:09:30,810 --> 00:09:34,170 for a file called employee.rs. 200 00:09:34,170 --> 00:09:38,580 So in mystructs, we have employee.rs 201 00:09:38,580 --> 00:09:43,200 and in here we define our employee structure 202 00:09:43,200 --> 00:09:47,223 and it implements, let's see what's going on here. 203 00:09:49,710 --> 00:09:53,797 So, there's another interface or another trait called log. 204 00:09:55,110 --> 00:09:56,550 We'll have a look at that later. 205 00:09:56,550 --> 00:09:58,320 Ignore that for now. 206 00:09:58,320 --> 00:10:02,700 Here is the data structure for my employee. 207 00:10:02,700 --> 00:10:04,770 An employee has a name, and a salary, 208 00:10:04,770 --> 00:10:06,660 and a full-time status. 209 00:10:06,660 --> 00:10:08,790 Okay? So that's just the data. 210 00:10:08,790 --> 00:10:11,190 And then we have the regular functionality, 211 00:10:11,190 --> 00:10:12,930 nothing to do with traits. 212 00:10:12,930 --> 00:10:16,230 Just the kind of basic functionality for an employee. 213 00:10:16,230 --> 00:10:20,730 An employee has a method to give the employee a payrise, 214 00:10:20,730 --> 00:10:22,593 a handsome payrise, I hope. 215 00:10:23,460 --> 00:10:25,950 Oh, also it has an associated function 216 00:10:25,950 --> 00:10:28,320 to create a new employee with a name, 217 00:10:28,320 --> 00:10:30,540 and a salary, and a full-time status. 218 00:10:30,540 --> 00:10:33,090 So we've seen this kind of thing before. 219 00:10:33,090 --> 00:10:35,940 As well as that, this is the implementation 220 00:10:35,940 --> 00:10:38,400 of the Print trait for Employee. 221 00:10:38,400 --> 00:10:40,590 Just the Print trait here. 222 00:10:40,590 --> 00:10:42,510 It's like a slicing mechanism, 223 00:10:42,510 --> 00:10:45,810 altogether you define the data for the employee. 224 00:10:45,810 --> 00:10:49,830 Its regular implementation, how it implements one trait, 225 00:10:49,830 --> 00:10:51,420 and how it implements another trait. 226 00:10:51,420 --> 00:10:53,550 It's all very piecemeal step by step. 227 00:10:53,550 --> 00:10:55,980 And I actually quite like that in rust. 228 00:10:55,980 --> 00:10:57,990 It's quite clear to see this is just 229 00:10:57,990 --> 00:11:00,690 how it implements the Print trait. 230 00:11:00,690 --> 00:11:02,430 So, to implement the Print trait, 231 00:11:02,430 --> 00:11:05,880 remember, the Print trait was here 232 00:11:05,880 --> 00:11:08,340 and it says if you implement the Print trait, 233 00:11:08,340 --> 00:11:12,000 you must have a print function. 234 00:11:12,000 --> 00:11:16,830 So, we do, if we implement the Print trait, 235 00:11:16,830 --> 00:11:19,023 then we must have a print function. 236 00:11:19,920 --> 00:11:21,570 Here is the print function. 237 00:11:21,570 --> 00:11:23,550 It's implicitly public. 238 00:11:23,550 --> 00:11:25,650 When you implement a trait, 239 00:11:25,650 --> 00:11:27,480 the function is implicitly public. 240 00:11:27,480 --> 00:11:29,130 You don't have to say pub anymore. 241 00:11:29,130 --> 00:11:32,250 The whole thing about interfaces is public interface. 242 00:11:32,250 --> 00:11:34,560 It is implicitly public 243 00:11:34,560 --> 00:11:37,980 and it is an instance method 244 00:11:37,980 --> 00:11:41,040 you would say employee1.print 245 00:11:41,040 --> 00:11:43,860 and it'll print the person's name, how much they earn, 246 00:11:43,860 --> 00:11:45,393 and their full-time status. 247 00:11:46,800 --> 00:11:50,490 Okay, so finally then back up to main. 248 00:11:50,490 --> 00:11:52,680 Let's see how to actually use all this. 249 00:11:52,680 --> 00:11:55,140 Demo trait essentials. 250 00:11:55,140 --> 00:11:56,890 That's the code we're going to run. 251 00:11:57,750 --> 00:12:00,423 And it's here. 252 00:12:01,698 --> 00:12:06,240 So we import from the top level namespace, 253 00:12:06,240 --> 00:12:09,180 we import the mytraits module 254 00:12:09,180 --> 00:12:11,470 which defined a submodule called print 255 00:12:12,390 --> 00:12:15,630 which defined a Print trait. 256 00:12:15,630 --> 00:12:20,110 Okay? So from the top level, go into the mytraits module 257 00:12:21,450 --> 00:12:23,913 which defined a submodule called print, 258 00:12:25,080 --> 00:12:26,670 which is here. 259 00:12:26,670 --> 00:12:30,330 And in there, it defined the Print trait. 260 00:12:30,330 --> 00:12:32,170 So, import that into scope 261 00:12:33,540 --> 00:12:38,470 and then also import the employee structure into scope 262 00:12:39,330 --> 00:12:40,560 and then just use it. 263 00:12:40,560 --> 00:12:44,670 So we create an employee, we invoke its regular method, 264 00:12:44,670 --> 00:12:47,760 and then we invoke its print related function here. 265 00:12:47,760 --> 00:12:51,003 Okay? So what we do now is run and hope. 266 00:12:52,380 --> 00:12:55,213 (keyboard typing) 267 00:12:56,380 --> 00:12:58,320 Okay? I have a high level of confidence 268 00:12:58,320 --> 00:12:59,520 that this is gonna work. 269 00:13:00,630 --> 00:13:01,650 So what it's doing at the moment, 270 00:13:01,650 --> 00:13:03,990 it's just importing various dependencies 271 00:13:03,990 --> 00:13:05,880 from the Cargo.toml. 272 00:13:05,880 --> 00:13:07,860 I've imported the chrono dependency. 273 00:13:07,860 --> 00:13:08,850 We've seen that a few times, 274 00:13:08,850 --> 00:13:10,860 it also inputs other dependencies. 275 00:13:10,860 --> 00:13:14,550 So those account be being compiled at the moment 276 00:13:14,550 --> 00:13:16,470 and when it's downloaded all of those 277 00:13:16,470 --> 00:13:19,620 it'll then actually run the code, create the employee, 278 00:13:19,620 --> 00:13:21,870 give the employee a rather meager payrise. 279 00:13:21,870 --> 00:13:24,300 I think that's probably not enough money, is it really? 280 00:13:24,300 --> 00:13:25,650 And then print the details afterwards. 281 00:13:25,650 --> 00:13:29,040 So after that payrise, John now earns 200 units 282 00:13:29,040 --> 00:13:30,690 and he's not a full-timer. 283 00:13:30,690 --> 00:13:33,060 Right. So that's a simple example of traits. 284 00:13:33,060 --> 00:13:34,840 You define the trait in one file 285 00:13:35,850 --> 00:13:38,730 and then you implement it in a structure. 286 00:13:38,730 --> 00:13:41,760 You have an implementation block for each trait 287 00:13:41,760 --> 00:13:43,020 that you want to implement. 288 00:13:43,020 --> 00:13:45,993 You have a separate implementation block for that trait.