1 00:00:12,000 --> 00:00:16,000 This presentation is delivered by the Stanford Center for Professional 2 00:00:16,000 --> 00:00:18,000 Development. 3 00:00:24,000 --> 00:00:28,000 Hey there. All right. So thank you very much for your 4 00:00:28,000 --> 00:00:30,000 duty to the CS106B 5 00:00:30,000 --> 00:00:33,000 midterm exam last night. An 6 00:00:33,000 --> 00:00:38,000 unusual event by all accounts, but we did all manage to get it done. Okay. 7 00:00:38,000 --> 00:00:41,000 Well, good. I'll finish - 8 00:00:41,000 --> 00:00:44,000 this is the last slide that we had shown on Friday. And 9 00:00:44,000 --> 00:00:45,000 I had 10 00:00:45,000 --> 00:00:48,000 just blasted it up there and then didn't really talk about it. So I'm gonna talk about it 11 00:00:48,000 --> 00:00:51,000 now and then just finish the final adjustment we're gonna make to this, right? So 12 00:00:51,000 --> 00:00:53,000 this is - the selection sort 13 00:00:53,000 --> 00:00:57,000 code that we have worked to templatize and do a template function, 14 00:00:57,000 --> 00:01:01,000 and now it will sort vectors of unknown type. 15 00:01:01,000 --> 00:01:04,000 And the change we just made - the one that's highlighted here in blue - 16 00:01:04,000 --> 00:01:09,000 was rather than directly taking V sub J, V sub X and comparing them using a 17 00:01:09,000 --> 00:01:10,000 less than - 18 00:01:10,000 --> 00:01:13,000 is that we're using a call back function. Call back functions - the 19 00:01:13,000 --> 00:01:15,000 parameter CMP, or compare there, 20 00:01:15,000 --> 00:01:17,000 takes two parameters that are of 21 00:01:17,000 --> 00:01:21,000 the client's type, returns an N - which is their ordering - zero, negative or positive, 22 00:01:21,000 --> 00:01:26,000 and then, instead of making a direct expression involving less than, we're 23 00:01:26,000 --> 00:01:29,000 evoking the client's call back on the two things that we need to compare and 24 00:01:29,000 --> 00:01:32,000 saying if that result is less than zero - so V sub J 25 00:01:32,000 --> 00:01:35,000 precedes the V of the main index. So it's actually smaller than the main element 26 00:01:35,000 --> 00:01:39,000 we've seen so far. Then we update our main index 27 00:01:39,000 --> 00:01:41,000 to record J as the 28 00:01:41,000 --> 00:01:44,000 place we've seen it. And then it goes to the rest of the code normally swapping that 29 00:01:44,000 --> 00:01:45,000 small thing out to the front 30 00:01:45,000 --> 00:01:49,000 and then going back around for multiple iterations to keep doing that. 31 00:01:49,000 --> 00:01:51,000 With this change, right? 32 00:01:51,000 --> 00:01:54,000 We have now kind of generalized this fully in a way that you can sort 33 00:01:54,000 --> 00:01:56,000 vectors or strings or vectors of 34 00:01:56,000 --> 00:02:01,000 coordinate structures or students or vectors of sets of things as long as the 35 00:02:01,000 --> 00:02:02,000 client 36 00:02:02,000 --> 00:02:05,000 supplies the appropriate comparison function that explains how do you want those 37 00:02:05,000 --> 00:02:06,000 things ordered? 38 00:02:06,000 --> 00:02:09,000 Which ones go in the front? Which ones go in the back? It's up to the client to say 39 00:02:09,000 --> 00:02:11,000 by giving us 40 00:02:11,000 --> 00:02:12,000 that call back. 41 00:02:12,000 --> 00:02:16,000 And so a client could use this, for example, to sort 42 00:02:16,000 --> 00:02:19,000 coordinates - something that has kind of an X and a Y field 43 00:02:19,000 --> 00:02:22,000 by deciding that, ''Well, if - 44 00:02:22,000 --> 00:02:23,000 first, from the base of the X coordinate, the 45 00:02:23,000 --> 00:02:26,000 first one's X coordinate precedes the other, than it's considered less than.'' You have to 46 00:02:26,000 --> 00:02:29,000 make up an ordering, right? That represents what you want, and in this case, I'm gonna say that, 47 00:02:29,000 --> 00:02:32,000 ''Well, first sort on the X dimension, 48 00:02:32,000 --> 00:02:35,000 moving smaller values of X to the front. 49 00:02:35,000 --> 00:02:38,000 And where they are tied in the X dimension, then use the Y to break ties 50 00:02:38,000 --> 00:02:39,000 here - 51 00:02:39,000 --> 00:02:42,000 looking at the Y fields - if it has gotten through those first 52 00:02:42,000 --> 00:02:43,000 cases of X 53 00:02:43,000 --> 00:02:45,000 compared between C1 and C2. 54 00:02:45,000 --> 00:02:47,000 And if all of those things have kind of 55 00:02:47,000 --> 00:02:50,000 not been through, then we know that, at this point, X and Y are exactly equal. And so we 56 00:02:50,000 --> 00:02:53,000 have two elements that are the same.'' 57 00:02:53,000 --> 00:02:54,000 And so, given a vector of chord, 58 00:02:54,000 --> 00:02:56,000 right? I would invoke sort 59 00:02:56,000 --> 00:03:00,000 passing that vector and then the matching comparison function 60 00:03:00,000 --> 00:03:02,000 that lets the 61 00:03:02,000 --> 00:03:03,000 sorting routine know how to take 62 00:03:03,000 --> 00:03:10,000 two chords and decide which goes in front. Yes, 63 00:03:10,000 --> 00:03:12,000 sir. Student:Where we use the type-name 64 00:03:12,000 --> 00:03:13,000 template - Um hm. 65 00:03:13,000 --> 00:03:16,000 Student:Is type name a 66 00:03:16,000 --> 00:03:21,000 special word? It is. So the type name is a C++ key word that says, ''This template depends 67 00:03:21,000 --> 00:03:24,000 on a type name.'' There are actually other things you can templatize on. We 68 00:03:24,000 --> 00:03:27,000 won't see that this quarter, but I'll just kind of leave it as a 69 00:03:27,000 --> 00:03:30,000 - things - that there are other things that you may actually have as kind of 70 00:03:30,000 --> 00:03:32,000 parameters to the pattern that you're using. The 71 00:03:32,000 --> 00:03:36,000 one we're gonna see is when you are actually using a type as a placeholder. And so type name means 72 00:03:36,000 --> 00:03:38,000 there's a type in 73 00:03:38,000 --> 00:03:40,000 the body that follows, right? 74 00:03:40,000 --> 00:03:42,000 There will be usage of the key word of a - 75 00:03:42,000 --> 00:03:46,000 our chosen word, type, as a placeholder for something that is 76 00:03:46,000 --> 00:03:49,000 supposed to be a type name. 77 00:03:49,000 --> 00:03:51,000 The other word there - 78 00:03:51,000 --> 00:03:52,000 they type, 79 00:03:52,000 --> 00:03:56,000 right? That was our choice. That could be T or E or F or my type or whatever it is 80 00:03:56,000 --> 00:04:02,000 I wanted. That was just a name we got to pick. 81 00:04:02,000 --> 00:04:04,000 That my core compare - 82 00:04:04,000 --> 00:04:06,000 and the last thing I'm gonna do with this 83 00:04:06,000 --> 00:04:10,000 is just make it a little bit more convenient that - given the form I have right now, it 84 00:04:10,000 --> 00:04:13,000 says that really, ''Oh, there's gonna be two parameters. You're gonna give it a vector, and 85 00:04:13,000 --> 00:04:15,000 you're gonna give it a comparison 86 00:04:15,000 --> 00:04:16,000 call back function.'' 87 00:04:16,000 --> 00:04:20,000 Before I went through all this trouble to make it have a comparison function, it used to actually 88 00:04:20,000 --> 00:04:23,000 just work by default for things like ents and doubles and strings that 89 00:04:23,000 --> 00:04:26,000 actually already operated correctly with less than. 90 00:04:26,000 --> 00:04:30,000 And so what I'm gonna do is I'm gonna - having made it generalizable, I'm also gonna go 91 00:04:30,000 --> 00:04:34,000 back and add in a default behavior which says, ''If you don't care, otherwise, 92 00:04:34,000 --> 00:04:38,000 and the default less than would work for you, then let's go ahead and use that 93 00:04:38,000 --> 00:04:41,000 unless otherwise indicated.'' So that, kinda, we got back the original behavior we 94 00:04:41,000 --> 00:04:44,000 wanted, which is you get to say, ''Sort a vector of numbers and have it do the right thing 95 00:04:44,000 --> 00:04:48,000 without having to go to the trouble of building a compare ent function 96 00:04:48,000 --> 00:04:50,000 to pass to it.'' 97 00:04:50,000 --> 00:04:53,000 So what we will do is we have an operator compare - 98 00:04:53,000 --> 00:04:54,000 I'll show you what it looks like here - 99 00:04:54,000 --> 00:04:58,000 that there is another header file in the 106B collection called CMPfunction.H. 100 00:04:58,000 --> 00:04:59,000 101 00:04:59,000 --> 00:05:02,000 It looks like this. It is a template function itself. It's called operator 102 00:05:02,000 --> 00:05:05,000 compare that takes two type things, 103 00:05:05,000 --> 00:05:08,000 and then it uses equals, equals and less than to decide whether to return a 104 00:05:08,000 --> 00:05:10,000 zero, a negative one or a one. 105 00:05:10,000 --> 00:05:12,000 And so operator compare will only work 106 00:05:12,000 --> 00:05:16,000 when instantiated for types for which the built in equals, equals and less than 107 00:05:16,000 --> 00:05:18,000 are defined and make sense. Now - and 108 00:05:18,000 --> 00:05:22,000 that includes all the built - the regular prototypes and double and whatnot, and also includes 109 00:05:22,000 --> 00:05:23,000 the string class 110 00:05:23,000 --> 00:05:24,000 and then 111 00:05:24,000 --> 00:05:27,000 potentially other classes, right? That you may know of that actually have behaviors 112 00:05:27,000 --> 00:05:29,000 that have implemented those operators. 113 00:05:29,000 --> 00:05:31,000 It will not work on things like struts 114 00:05:31,000 --> 00:05:35,000 or vectors or other things that don't have the behavior for this. And 115 00:05:35,000 --> 00:05:38,000 it's not intended for those. It's kinda just a pattern for which you can build this 116 00:05:38,000 --> 00:05:40,000 - 117 00:05:40,000 --> 00:05:42,000 the comparison function needed 118 00:05:42,000 --> 00:05:43,000 for the form by sort. 119 00:05:43,000 --> 00:05:46,000 And so then I change the prototype here of sort. It 120 00:05:46,000 --> 00:05:47,000 takes a vector of that type. 121 00:05:47,000 --> 00:05:51,000 It takes a comparison function. It takes these two things, and then I said, ''A deep-hole 122 00:05:51,000 --> 00:05:54,000 argument for that is to use operator compare.'' 123 00:05:54,000 --> 00:05:56,000 And so when somebody invokes sort 124 00:05:56,000 --> 00:05:58,000 not passing the second argument, 125 00:05:58,000 --> 00:06:02,000 then what that will cause the code to do is say, ''Okay. Well, they didn't pass it. We 126 00:06:02,000 --> 00:06:06,000 need to use the default expression over here, and then operator compare 127 00:06:06,000 --> 00:06:09,000 will be instantiated for whatever the type is.'' 128 00:06:09,000 --> 00:06:13,000 So if it was string, then it will build operator compare that operates on strings. If 129 00:06:13,000 --> 00:06:15,000 they were ent or double or anything 130 00:06:15,000 --> 00:06:17,000 that has a 131 00:06:17,000 --> 00:06:20,000 meaningful way to apply the built-in operators if we use that - 132 00:06:20,000 --> 00:06:26,000 if I still called sort in this case, past let's say, vector of chords - if I went back to this picture - 133 00:06:26,000 --> 00:06:28,000 and I forgot this argument, 134 00:06:28,000 --> 00:06:31,000 right? I will get a compiler. And a complier will come from 135 00:06:31,000 --> 00:06:35,000 trying to instantiate an operator compare that works on chord where it will get to 136 00:06:35,000 --> 00:06:38,000 that line about equals, equals and less than, and say, ''You're comparing two structure 137 00:06:38,000 --> 00:06:40,000 types, and that doesn't make sense to me.'' 138 00:06:40,000 --> 00:06:43,000 So in this case, the client has the choice of 139 00:06:43,000 --> 00:06:45,000 specifying it 140 00:06:45,000 --> 00:06:48,000 when they intend it to control that behavior or they need to control that 141 00:06:48,000 --> 00:06:52,000 behavior. They can also leave it off in the cases where that default of operator 142 00:06:52,000 --> 00:06:55,000 compare will do what they wanted anyway. 143 00:06:55,000 --> 00:06:57,000 So I have an example here at the end 144 00:06:57,000 --> 00:06:59,000 that says, ''If I wanted to sort an array of numbers, 145 00:06:59,000 --> 00:07:04,000 I won't need to pass a second argument in the case where I just want to sort it in 146 00:07:04,000 --> 00:07:06,000 ordinary increasing order.'' 147 00:07:06,000 --> 00:07:09,000 If I wanted, for example, to sort it in inverted order - I want the largest value to 148 00:07:09,000 --> 00:07:11,000 come to the front - 149 00:07:11,000 --> 00:07:14,000 that I don't need to run a new sorting routine that then goes and looks for the max and pulls it to the front. 150 00:07:14,000 --> 00:07:17,000 I just need to trick selection sort here 151 00:07:17,000 --> 00:07:20,000 into believing that the larger numbers go in front of the smaller ones. 152 00:07:20,000 --> 00:07:23,000 So I basically wrote an inverted compare function 153 00:07:23,000 --> 00:07:28,000 that if A is less than B, it returns one, which basically says, ''Well, B goes before A 154 00:07:28,000 --> 00:07:32,000 in the ordering I want, which is the larger one should precede it in the output, 155 00:07:32,000 --> 00:07:36,000 and similarly for the other case, and then returning zero when they're the same.'' 156 00:07:36,000 --> 00:07:38,000 So this gives us control when we want it 157 00:07:38,000 --> 00:07:42,000 in the case of the primitives as well as control when we need it 158 00:07:42,000 --> 00:07:46,000 for those types for which the built-ins don't have defined behavior for it. 159 00:07:46,000 --> 00:07:51,000 So this makes this, like, the end-all, be-all sorting template. 160 00:07:51,000 --> 00:07:53,000 Everything you could want in one package. 161 00:07:53,000 --> 00:07:55,000 You will be running something that looks just like this 162 00:07:55,000 --> 00:07:58,000 for the second part of the assignment this week, 163 00:07:58,000 --> 00:08:01,000 and then what will differ is - well how does it do its work? What strategy is it using 164 00:08:01,000 --> 00:08:02,000 to get things in order? 165 00:08:02,000 --> 00:08:04,000 But the overall design of it is 166 00:08:04,000 --> 00:08:08,000 to build this general purpose, could be used for everything, has a client call back 167 00:08:08,000 --> 00:08:09,000 option, 168 00:08:09,000 --> 00:08:11,000 also has a default used 169 00:08:11,000 --> 00:08:14,000 that makes for very nice, convenient as a client. 170 00:08:14,000 --> 00:08:17,000 Any questions about that? It 171 00:08:17,000 --> 00:08:19,000 is your life. Student:I have 172 00:08:19,000 --> 00:08:21,000 a question on the [inaudible]. Yeah. 173 00:08:21,000 --> 00:08:24,000 Student:Right below the void line - Uh huh. 174 00:08:24,000 --> 00:08:25,000 Student:So what does that do? 175 00:08:25,000 --> 00:08:29,000 So the line that's underneath this one? Student:Yeah. This one here? So this is the one that says, 176 00:08:29,000 --> 00:08:33,000 ''The second parameter - the first parameter's a vector of type by reference. The second - 177 00:08:33,000 --> 00:08:37,000 it says the second parameter is a comparison function that takes two type 178 00:08:37,000 --> 00:08:38,000 arguments and returns it in, 179 00:08:38,000 --> 00:08:41,000 and the default assignment to that parameter, if you have not specified it, 180 00:08:41,000 --> 00:08:44,000 will be to use operator compare.'' 181 00:08:44,000 --> 00:08:47,000 That's got a lot of things mashed in there. The syntax for the 182 00:08:47,000 --> 00:08:51,000 passing a function as a parameter is a little bit goopy in C++. It kinda 183 00:08:51,000 --> 00:08:53,000 includes what looks like a full prototype because 184 00:08:53,000 --> 00:08:56,000 that describes for the compiler, ''Well, what kind of functions are they?'' And they have to 185 00:08:56,000 --> 00:09:01,000 have this parameters in this order - this return type. So we actually kind of have to give this 186 00:09:01,000 --> 00:09:02,000 full information about 187 00:09:02,000 --> 00:09:04,000 what the 188 00:09:04,000 --> 00:09:08,000 shape of such a function is so that it can match it. It can't just take any 189 00:09:08,000 --> 00:09:10,000 function, right? It can't pass it get line or 190 00:09:10,000 --> 00:09:13,000 191 00:09:13,000 --> 00:09:15,000 convert to lower case - like, not just any function is good. I need to 192 00:09:15,000 --> 00:09:18,000 give a description of what kind of functions are right, and those are the kind of functions 193 00:09:18,000 --> 00:09:20,000 that take two type arguments and return an ent. 194 00:09:20,000 --> 00:09:21,000 And that's what - we're 195 00:09:21,000 --> 00:09:26,000 helping the compiler out there with all that syntax. Student:How will it know if you have a comparison function based 196 00:09:26,000 --> 00:09:27,000 on that 197 00:09:27,000 --> 00:09:30,000 call? So this isn't the call, right? This is the function I defined. So when I make a 198 00:09:30,000 --> 00:09:32,000 call to sort - so if I look at this one - 199 00:09:32,000 --> 00:09:35,000 it's all a matter of, ''Do I pass one argument or two?'' Student:All 200 00:09:35,000 --> 00:09:39,000 right. It's just a default argument. If I don't specify it, then it will use the default 201 00:09:39,000 --> 00:09:42,000 value, just like any of the default argument things we know about, like find on a 202 00:09:42,000 --> 00:09:43,000 string, which 203 00:09:43,000 --> 00:09:46,000 if you don't say, it will start at position zero doing a search. 204 00:09:46,000 --> 00:09:49,000 If you do specify, then it uses your 205 00:09:49,000 --> 00:09:56,000 index instead. All right? Yeah. Let 206 00:09:56,000 --> 00:09:58,000 me move on. 207 00:09:58,000 --> 00:09:59,000 208 00:09:59,000 --> 00:10:01,000 So in your 106A class, right? You did a lot 209 00:10:01,000 --> 00:10:04,000 of things in the genre of object-oriented programming. 210 00:10:04,000 --> 00:10:08,000 This class is not really an object-oriented programming class. It's a class of - that's, 211 00:10:08,000 --> 00:10:11,000 in many ways, very procedural, but we use a lot of 212 00:10:11,000 --> 00:10:12,000 objects. 213 00:10:12,000 --> 00:10:15,000 And what I want to do, just for a minute here, is just kind of 214 00:10:15,000 --> 00:10:19,000 reiterate the advantages of using objects in your code - 215 00:10:19,000 --> 00:10:23,000 what it is that they provide in terms of structuring and engineering and working to a 216 00:10:23,000 --> 00:10:24,000 solution. 217 00:10:24,000 --> 00:10:26,000 And then we're gonna go on and start 218 00:10:26,000 --> 00:10:30,000 talking about, ''Well, we used a lot of objects. What does the other side look like? What is it like to 219 00:10:30,000 --> 00:10:30,000 implement 220 00:10:30,000 --> 00:10:31,000 an object 221 00:10:31,000 --> 00:10:35,000 starting from scratch? What pieces need to be done, and how does that work? 222 00:10:35,000 --> 00:10:39,000 And so the idea of just object-oriented programming is actually - it's a relatively new 223 00:10:39,000 --> 00:10:41,000 concept in computer programming, right? It only dates back 224 00:10:41,000 --> 00:10:43,000 to the e80s, 225 00:10:43,000 --> 00:10:47,000 and the realization, right? That programs at that time - we were operating on 226 00:10:47,000 --> 00:10:50,000 a lot of data and moving around employees, or you're managing this calendar, 227 00:10:50,000 --> 00:10:53,000 which has these events that are at certain times. 228 00:10:53,000 --> 00:10:56,000 And that you had a lot of operations that were, obviously, intended to work on 229 00:10:56,000 --> 00:11:00,000 that data - like, move this event to another time or calculate whether this 230 00:11:00,000 --> 00:11:04,000 time perceives another - conflicts with this. 231 00:11:04,000 --> 00:11:08,000 And that operations, though - the functions that manipulate that data and the data 232 00:11:08,000 --> 00:11:11,000 itself - were not really very tightly coupled in the kinda past. 233 00:11:11,000 --> 00:11:14,000 And the idea of [inaudible] used to really couple those things together - to say 234 00:11:14,000 --> 00:11:15,000 that, 235 00:11:15,000 --> 00:11:18,000 ''If you have a data type like a time or a stack 236 00:11:18,000 --> 00:11:19,000 or a vector, 237 00:11:19,000 --> 00:11:22,000 that the operations that manipulate a vector 238 00:11:22,000 --> 00:11:23,000 are best made 239 00:11:23,000 --> 00:11:27,000 as part of the package of vector itself - that rather than there being a print 240 00:11:27,000 --> 00:11:31,000 vector function that operates somewhere else, having vector-heavy print method.'' 241 00:11:31,000 --> 00:11:34,000 Putting something onto a stack or asking it for it's size 242 00:11:34,000 --> 00:11:37,000 is really an operation that should be owned by the stack - that a stack variable 243 00:11:37,000 --> 00:11:41,000 should be able to respond to requests to do things on your behalf 244 00:11:41,000 --> 00:11:42,000 through messaging. 245 00:11:42,000 --> 00:11:46,000 And so this idea has become kind of 246 00:11:46,000 --> 00:11:48,000 247 00:11:48,000 --> 00:11:51,000 permeated the language design in the last decade or so to 248 00:11:51,000 --> 00:11:55,000 where pretty much every modern language has some facility for object orientation. 249 00:11:55,000 --> 00:11:55,000 250 00:11:55,000 --> 00:11:59,000 Even older languages that didn't before have been updated and brought forward, 251 00:11:59,000 --> 00:12:01,000 right? To visual basic, right? Basic, which 252 00:12:01,000 --> 00:12:06,000 has been around for half a century, is now objectified, 253 00:12:06,000 --> 00:12:08,000 right? In these latest versions. 254 00:12:08,000 --> 00:12:11,000 So [inaudible] that the leverage to the real world is actually an important part of the 255 00:12:11,000 --> 00:12:15,000 advantage that, when you talk about a time or a stack or an event or a message if 256 00:12:15,000 --> 00:12:16,000 you're doing a mail program - 257 00:12:16,000 --> 00:12:20,000 those things have real-world meaning. And so the idea of what they do and how they 258 00:12:20,000 --> 00:12:21,000 act 259 00:12:21,000 --> 00:12:23,000 actually has - there's a lot of leverage of what you already know to be true 260 00:12:23,000 --> 00:12:27,000 about those things in the real world. The 261 00:12:27,000 --> 00:12:30,000 notion of kind of dividing it up and saying, ''Here's this abstraction of what a 262 00:12:30,000 --> 00:12:34,000 stack is,'' - so we've used stacks all along. Push and pop, right? Push and 263 00:12:34,000 --> 00:12:36,000 pop. What does it really do? How does it 264 00:12:36,000 --> 00:12:40,000 really manage stuff? Where's the memory coming from? What internal structures? It's not 265 00:12:40,000 --> 00:12:43,000 actually something we have to worry about. We're using it abstractly. We're saying, ''It's 266 00:12:43,000 --> 00:12:46,000 a stack. It has push and pop behaviors.'' 267 00:12:46,000 --> 00:12:49,000 All the other details of how it works are not something we have to worry about. 268 00:12:49,000 --> 00:12:52,000 So let's just focus on some of the other problems - more interesting problems than 269 00:12:52,000 --> 00:12:54,000 the kind of things that happen behind the scenes. 270 00:12:54,000 --> 00:12:57,000 They're also very tightly encapsulated. So we're not 271 00:12:57,000 --> 00:13:01,000 mucking with the stack. It's actually acting force as a black box with - it's kinda like one of 272 00:13:01,000 --> 00:13:04,000 those microwaves where it says on the back, ''If you take this panel off, right? You void 273 00:13:04,000 --> 00:13:05,000 your warrantee.'' 274 00:13:05,000 --> 00:13:08,000 Like, I don't know how my microwave works. I never take that panel off. I hit the panels 275 00:13:08,000 --> 00:13:09,000 on the front, food gets hot - 276 00:13:09,000 --> 00:13:12,000 I'm very happy. 277 00:13:12,000 --> 00:13:15,000 And then things that happen in the large - as you get to building larger and 278 00:13:15,000 --> 00:13:19,000 larger projects, right? The idea that multiple engineers are working together 279 00:13:19,000 --> 00:13:22,000 and designing on different timeframes - that having things divided in these very 280 00:13:22,000 --> 00:13:25,000 strongly capsulated bundles 281 00:13:25,000 --> 00:13:29,000 makes it possible to design and test independently of your partners and then join 282 00:13:29,000 --> 00:13:31,000 back together and have 283 00:13:31,000 --> 00:13:33,000 a much better 284 00:13:33,000 --> 00:13:36,000 eventual result that, if everybody's trying to write all the same code in the same places 285 00:13:36,000 --> 00:13:38,000 on top of each other without 286 00:13:38,000 --> 00:13:40,000 real discipline to it. 287 00:13:40,000 --> 00:13:44,000 Nice packaging for reuse Something we've been seeing a lot if, right? Is the things that - 288 00:13:44,000 --> 00:13:46,000 Lexicon 289 00:13:46,000 --> 00:13:50,000 or stack or hue we've used in a lot of different ways - sort 290 00:13:50,000 --> 00:13:52,000 of a multi-purpose 291 00:13:52,000 --> 00:13:54,000 object. 292 00:13:54,000 --> 00:13:55,000 Let me tell you about what - 293 00:13:55,000 --> 00:13:56,000 who does what 294 00:13:56,000 --> 00:13:59,000 in here and what new rules we're moving into, right? 295 00:13:59,000 --> 00:14:03,000 We have done a lot of client use of objects. So a 296 00:14:03,000 --> 00:14:07,000 program like the maze program or the random-writer program is some code file 297 00:14:07,000 --> 00:14:10,000 containing actual code - .cpp. 298 00:14:10,000 --> 00:14:13,000 It messages to objects. It creates objects. It asks them to do things on 299 00:14:13,000 --> 00:14:14,000 its behalf. 300 00:14:14,000 --> 00:14:18,000 Every class that it is using, it includes the class.h - so stack.h 301 00:14:18,000 --> 00:14:20,000 or que.h or vector.h 302 00:14:20,000 --> 00:14:21,000 based on what it needs. 303 00:14:21,000 --> 00:14:25,000 And so this is the only role we have played so far. We've been client. We've used 304 00:14:25,000 --> 00:14:28,000 them, but we don't know anything about these other two things that need to get 305 00:14:28,000 --> 00:14:29,000 done. 306 00:14:29,000 --> 00:14:30,000 In the middle, 307 00:14:30,000 --> 00:14:33,000 between the client and the implementation here, 308 00:14:33,000 --> 00:14:35,000 is something called the interface. 309 00:14:35,000 --> 00:14:38,000 We have looked at these header files like stack.h and que.h, 310 00:14:38,000 --> 00:14:41,000 and that tells you about what the class provides - 311 00:14:41,000 --> 00:14:43,000 what abstraction it is, 312 00:14:43,000 --> 00:14:47,000 what it's member functions are, what they're names are, what they're parameters are, 313 00:14:47,000 --> 00:14:50,000 what the usage - the correct usage of it is. 314 00:14:50,000 --> 00:14:52,000 And so this serves as 315 00:14:52,000 --> 00:14:53,000 information 316 00:14:53,000 --> 00:14:54,000 to the client 317 00:14:54,000 --> 00:14:56,000 about what you can do and what you can't do, 318 00:14:56,000 --> 00:14:59,000 what's legal, what's available - 319 00:14:59,000 --> 00:15:00,000 and it doesn't contain any inner 320 00:15:00,000 --> 00:15:02,000 information about 321 00:15:02,000 --> 00:15:03,000 how does it really work? 322 00:15:03,000 --> 00:15:07,000 What does it do behind the scenes? What kind of thing can you expect other than kinda what's 323 00:15:07,000 --> 00:15:10,000 the correct behavior expected? What 324 00:15:10,000 --> 00:15:14,000 we're moving into, right? Is looking at this role and this 325 00:15:14,000 --> 00:15:16,000 role over here on the right, which is what is that implementation side work 326 00:15:16,000 --> 00:15:17,000 look like? 327 00:15:17,000 --> 00:15:22,000 So if we have described what Lexicon is - it's a word list where you can check for the 328 00:15:22,000 --> 00:15:25,000 existence of a word or the match of a prefix - 329 00:15:25,000 --> 00:15:27,000 and it's our job now to implement that, 330 00:15:27,000 --> 00:15:29,000 it's like, ''Well, what are we gonna do?'' Now this is where we get down and 331 00:15:29,000 --> 00:15:33,000 dirty, right? Now it's not about the pretty abstraction. It's about making it 332 00:15:33,000 --> 00:15:35,000 work - making it work. Well, making it work efficiently, 333 00:15:35,000 --> 00:15:39,000 using appropriate data structures, making it robust, 334 00:15:39,000 --> 00:15:42,000 making it handle kinda all kinds of things you throw at it. So for example, the vector 335 00:15:42,000 --> 00:15:43,000 class - 336 00:15:43,000 --> 00:15:46,000 if you ask it to get something that's off the index, right? 337 00:15:46,000 --> 00:15:49,000 It's gonna tell you about it, right? So taking care to make sure the thing just works 338 00:15:49,000 --> 00:15:52,000 in all situations, is very bullet proof, 339 00:15:52,000 --> 00:15:55,000 is very sturdy, is very informative, 340 00:15:55,000 --> 00:15:59,000 right? And well designed, sort of clean, easy to use, does the right things, 341 00:15:59,000 --> 00:16:01,000 has the right functionalities, isn't missing anything 342 00:16:01,000 --> 00:16:03,000 and that implements it well. 343 00:16:03,000 --> 00:16:08,000 And so in this file, the stack.cpp or the scanner.cpp, right? We have 344 00:16:08,000 --> 00:16:09,000 all the [inaudible] 345 00:16:09,000 --> 00:16:12,000 functions, so we make the things really happen. 346 00:16:12,000 --> 00:16:16,000 We include the class interface, too, because the interface is actually used by both people. 347 00:16:16,000 --> 00:16:20,000 The interface on this side tells the client what's there - what you can do. The interface tells 348 00:16:20,000 --> 00:16:22,000 the implementer what needs to work, 349 00:16:22,000 --> 00:16:26,000 right? You have offered up a method called contains prefix or contains 350 00:16:26,000 --> 00:16:28,000 word that is the implementation's job to make that thing do the right thing and 351 00:16:28,000 --> 00:16:34,000 return the right answer. 352 00:16:34,000 --> 00:16:35,000 So let's look at 353 00:16:35,000 --> 00:16:39,000 a simple class. The class I'm gonna talk you through is one of creating a time - 354 00:16:39,000 --> 00:16:43,000 sort of a moment in time - 2:15 - 355 00:16:43,000 --> 00:16:46,000 that potentially, right? You might be using, let's say, a calendaring program to 356 00:16:46,000 --> 00:16:49,000 decide what events you have scheduled for a particular day. You'd like to say, 357 00:16:49,000 --> 00:16:53,000 ''What's at this time?'' And then the idea of time and the things that manipulate time - it 358 00:16:53,000 --> 00:16:58,000 actually makes a very good object. It has a very real world analogue about what a time is. 359 00:16:58,000 --> 00:16:59,000 And there's a lot of 360 00:16:59,000 --> 00:17:02,000 behavior that seems to go with a time. 361 00:17:02,000 --> 00:17:04,000 So in the .h file, which is the interface for this, 362 00:17:04,000 --> 00:17:07,000 will be the listing of the class. So 363 00:17:07,000 --> 00:17:12,000 the outer structure for this - our class time and that open [inaudible], closed [inaudible] 364 00:17:12,000 --> 00:17:14,000 and then a closing semicolon. 365 00:17:14,000 --> 00:17:18,000 This kind of models the same syntax that C++ uses for struts. When you say 366 00:17:18,000 --> 00:17:20,000 strut something, and then you have these fields, and you also have this closing 367 00:17:20,000 --> 00:17:21,000 semicolon. 368 00:17:21,000 --> 00:17:25,000 That semicolon, right? Is not present in Java, and it's a pretty easy thing to leave off and 369 00:17:25,000 --> 00:17:29,000 then get a lot of [inaudible] error messages that are a little bit goofy from it. 370 00:17:29,000 --> 00:17:31,000 So one thing you must wanna 371 00:17:31,000 --> 00:17:32,000 register as something to 372 00:17:32,000 --> 00:17:34,000 be attentive to. 373 00:17:34,000 --> 00:17:38,000 What the interface declares - so this is separate in Java - 374 00:17:38,000 --> 00:17:41,000 not separate in Java. I'm saying in C++ it is - is there actually really is a file 375 00:17:41,000 --> 00:17:46,000 that says what the class provides, and there's another class that says how it works. In Java, those are kind 376 00:17:46,000 --> 00:17:48,000 of one and the same - that the 377 00:17:48,000 --> 00:17:51,000 definition of the class and the kind of interface of it were not separated and maintained 378 00:17:51,000 --> 00:17:52,000 separately. 379 00:17:52,000 --> 00:17:55,000 There are advantages to this and disadvantages. It means there's two 380 00:17:55,000 --> 00:17:59,000 separate files. That means that what you give to somebody who's using your code 381 00:17:59,000 --> 00:18:02,000 doesn't contain any of the things you don't want them to see - how it works 382 00:18:02,000 --> 00:18:04,000 and how it's internally 383 00:18:04,000 --> 00:18:05,000 configured. 384 00:18:05,000 --> 00:18:08,000 But it also means that you have to keep the two in sync - 385 00:18:08,000 --> 00:18:10,000 just the same way any kind of separate prototyping does - is if you change the 386 00:18:10,000 --> 00:18:13,000 name in one place, you have to change it in both places 387 00:18:13,000 --> 00:18:16,000 to kind of make sure that they're always in match. 388 00:18:16,000 --> 00:18:19,000 So the two main things that get declared within the class 389 00:18:19,000 --> 00:18:22,000 declaration or its interface are the data members - 390 00:18:22,000 --> 00:18:26,000 so the fields that are a part of a particular time object. 391 00:18:26,000 --> 00:18:29,000 And these are declared like ordinary variables in hour, minute. 392 00:18:29,000 --> 00:18:32,000 They can be variables of other types, string, vector and things like that as 393 00:18:32,000 --> 00:18:36,000 long as anything I'm using, I would have to [inaudible] include at the top. And 394 00:18:36,000 --> 00:18:40,000 in this case, I have introduced them under a private section. 395 00:18:40,000 --> 00:18:42,000 So unlike Java where 396 00:18:42,000 --> 00:18:45,000 every single field has it's own 397 00:18:45,000 --> 00:18:46,000 private or public modifier, 398 00:18:46,000 --> 00:18:50,000 in C++, you actually introduce a section with private [inaudible], 399 00:18:50,000 --> 00:18:53,000 and then everything from there on down is private until it sees something 400 00:18:53,000 --> 00:18:55,000 that changes that back to public. 401 00:18:55,000 --> 00:18:58,000 So typically, right? You'll have one big, public section, one smaller, private 402 00:18:58,000 --> 00:19:01,000 section - they can be in the other order 403 00:19:01,000 --> 00:19:04,000 - either way. I typically use this form where the public things sit at the top and the 404 00:19:04,000 --> 00:19:06,000 private beneath. 405 00:19:06,000 --> 00:19:09,000 The other things that get declared as part of your interface is what member functions are 406 00:19:09,000 --> 00:19:10,000 available. What 407 00:19:10,000 --> 00:19:11,000 are the operations 408 00:19:11,000 --> 00:19:14,000 that you can manipulate a time with? 409 00:19:14,000 --> 00:19:15,000 And so 410 00:19:15,000 --> 00:19:18,000 maybe right here, I have something that allows you to change the hour or get the current 411 00:19:18,000 --> 00:19:22,000 hour from a time or move it forward by some amount of hours and minutes. I wanna 412 00:19:22,000 --> 00:19:22,000 413 00:19:22,000 --> 00:19:25,000 push back that meaning by an hour and 50 minutes. I can 414 00:19:25,000 --> 00:19:27,000 call shift by 415 00:19:27,000 --> 00:19:29,000 1:45 to do that. 416 00:19:29,000 --> 00:19:33,000 Something that converts time into a string format may be suitable for 417 00:19:33,000 --> 00:19:35,000 printing or using in a display is 418 00:19:35,000 --> 00:19:38,000 a two-string member function I could add in the time class as part of its 419 00:19:38,000 --> 00:19:40,000 public interface. 420 00:19:40,000 --> 00:19:42,000 And so the whole list of what I have here 421 00:19:42,000 --> 00:19:44,000 - and so kind 422 00:19:44,000 --> 00:19:48,000 of as a rough rule, right? Most of your functions will end up public because they're 423 00:19:48,000 --> 00:19:50,000 operations you're offering. Your data is almost 424 00:19:50,000 --> 00:19:52,000 always 425 00:19:52,000 --> 00:19:55,000 private. You don't wanna make that accessible outside of the class. 426 00:19:55,000 --> 00:19:58,000 And then occasionally, right? There are reasons, actually, to have some 427 00:19:58,000 --> 00:19:59,000 member functions that are private. 428 00:19:59,000 --> 00:20:01,000 They're used internally as helpers, 429 00:20:01,000 --> 00:20:04,000 and they're part of the strategy, but they're not something you want a client to be 430 00:20:04,000 --> 00:20:06,000 able to directly call. So you actually 431 00:20:06,000 --> 00:20:10,000 keep them in the private section to 432 00:20:10,000 --> 00:20:11,000 indicate they're not 433 00:20:11,000 --> 00:20:13,000 part of the 434 00:20:13,000 --> 00:20:16,000 interface a client needs to know about. You 435 00:20:16,000 --> 00:20:22,000 see it all the time. Any questions about what it looks like there? 436 00:20:22,000 --> 00:20:23,000 So the time [inaudible] I have declared 437 00:20:23,000 --> 00:20:27,000 here has two data members - an integer hour and an integer minute. 438 00:20:27,000 --> 00:20:31,000 The mechanics of how this works is that the object is basically about the same size as the 439 00:20:31,000 --> 00:20:33,000 comparable strut. So it 440 00:20:33,000 --> 00:20:34,000 has 441 00:20:34,000 --> 00:20:35,000 fields for hour and minutes. 442 00:20:35,000 --> 00:20:39,000 It doesn't actually have a bunch of storage for the member functions. 443 00:20:39,000 --> 00:20:42,000 Since those are shared across all times, there's no reason that every time carry 444 00:20:42,000 --> 00:20:43,000 around a 445 00:20:43,000 --> 00:20:46,000 duplicate of that. So what it really carries is its own 446 00:20:46,000 --> 00:20:48,000 field - the 447 00:20:48,000 --> 00:20:50,000 data members that were declared in the class. 448 00:20:50,000 --> 00:20:52,000 And so when I say time T, what I'm 449 00:20:52,000 --> 00:20:56,000 getting space for - it looks a lot like a strut - something that has an hour and a minute field. 450 00:20:56,000 --> 00:21:00,000 By default, the initialization of this field is 451 00:21:00,000 --> 00:21:02,000 as it would be if they were to be declared on the stack. 452 00:21:02,000 --> 00:21:06,000 So if I said N to hour, N to minute, I would just get junk contest. So it doesn't set them to 453 00:21:06,000 --> 00:21:08,000 zero or do anything 454 00:21:08,000 --> 00:21:09,000 clever on our behalf. 455 00:21:09,000 --> 00:21:12,000 With these primitive types, it just lets them 456 00:21:12,000 --> 00:21:15,000 stay uninitialized. And we'll see about how to fix that in a minute, but just to know. 457 00:21:15,000 --> 00:21:19,000 And then when we talk about time objects, right? Every single time object has its own hour 458 00:21:19,000 --> 00:21:20,000 and minute. 459 00:21:20,000 --> 00:21:23,000 So this time is 2:15, this time is 7:00 p.m., 460 00:21:23,000 --> 00:21:24,000 and 461 00:21:24,000 --> 00:21:28,000 the numbers that they are storing and maintaining, right? Are 462 00:21:28,000 --> 00:21:34,000 different for their hour and minute. So it's kinda like across all the different time objects, there is 463 00:21:34,000 --> 00:21:38,000 individual hour and minute fields associated with each particular time. It 464 00:21:38,000 --> 00:21:41,000 all kinda seems to make sense back to the 106A days where you did a lot of 465 00:21:41,000 --> 00:21:45,000 this. 466 00:21:45,000 --> 00:21:48,000 But if you have a time object - and you've already seen this, but just 467 00:21:48,000 --> 00:21:52,000 to mention that - yeah, you access its member functions and its field using dot 468 00:21:52,000 --> 00:21:56,000 notation. If you happen to have a pointer, you can use the arrow, which combines the 469 00:21:56,000 --> 00:21:58,000 star and the dot, 470 00:21:58,000 --> 00:22:01,000 setting - calling set hour, calling get 471 00:22:01,000 --> 00:22:03,000 hour, trying to access a field 472 00:22:03,000 --> 00:22:08,000 that both the member function use and the field use is dependent on 473 00:22:08,000 --> 00:22:11,000 if the - the feature that I'm trying to access being declared public. 474 00:22:11,000 --> 00:22:14,000 It was in a private section, and if you don't 475 00:22:14,000 --> 00:22:18,000 specify - if you forget to put any of the [inaudible] specifiers on it - by default, they 476 00:22:18,000 --> 00:22:19,000 were all private. 477 00:22:19,000 --> 00:22:21,000 And so my attempt to 478 00:22:21,000 --> 00:22:24,000 access any of these things that were private will result in a compiler error. 479 00:22:24,000 --> 00:22:29,000 So it won't let me get past that kind of mistake. Now 480 00:22:29,000 --> 00:22:31,000 the message, we call that the receiver. 481 00:22:31,000 --> 00:22:34,000 And we talked about that before - T being the receiver to the set hour, 482 00:22:34,000 --> 00:22:38,000 and the assumption being that what I'm trying to do is tell this time object, right? 483 00:22:38,000 --> 00:22:40,000 To set the hour it is 484 00:22:40,000 --> 00:22:41,000 to 3:00, 485 00:22:41,000 --> 00:22:47,000 overriding whatever value was there before. 486 00:22:47,000 --> 00:22:50,000 Now what does it look like on the other side? 487 00:22:50,000 --> 00:22:54,000 If you are the implementer of time, 488 00:22:54,000 --> 00:22:58,000 what kind of things do you have to do to make time behave the way you said it would? 489 00:22:58,000 --> 00:23:00,000 You have a file timed out CPP - 490 00:23:00,000 --> 00:23:02,000 that's the class implementation file for it. 491 00:23:02,000 --> 00:23:05,000 The first thing it will always do is include the class file that it's working 492 00:23:05,000 --> 00:23:06,000 on. 493 00:23:06,000 --> 00:23:08,000 That's because if I start defining the features of 494 00:23:08,000 --> 00:23:11,000 class, I need to know what they are so the compiler can check and make sure that 495 00:23:11,000 --> 00:23:12,000 I've - 496 00:23:12,000 --> 00:23:16,000 I'm telling the truth, right? That the functions that I'm trying to implement 497 00:23:16,000 --> 00:23:19,000 and their parameters and the instance - the data members I'm trying to use 498 00:23:19,000 --> 00:23:22,000 match the description I earlier gave about what time was. 499 00:23:22,000 --> 00:23:25,000 So both the client needs to see it to use it. The 500 00:23:25,000 --> 00:23:28,000 implementer needs to see it to implement the right things that have the right 501 00:23:28,000 --> 00:23:31,000 names or the right prototypes. 502 00:23:31,000 --> 00:23:33,000 This is where all the code for the member function goes - 503 00:23:33,000 --> 00:23:34,000 is in this file. 504 00:23:34,000 --> 00:23:37,000 And there's a little bit of a 505 00:23:37,000 --> 00:23:38,000 syntax that 506 00:23:38,000 --> 00:23:40,000 you'll need to know about this, which is 507 00:23:40,000 --> 00:23:44,000 when I'm ready to implement the set hour member function, 508 00:23:44,000 --> 00:23:46,000 that the name that it goes by - 509 00:23:46,000 --> 00:23:51,000 its full name - its kinda real name - is time colon colon set hour - 510 00:23:51,000 --> 00:23:54,000 that everything that was defined in the time class is considered to be within 511 00:23:54,000 --> 00:23:56,000 this scope, 512 00:23:56,000 --> 00:24:00,000 and C++ is not the word for this. The scope time 513 00:24:00,000 --> 00:24:03,000 and - that the way to access something from within a scope 514 00:24:03,000 --> 00:24:06,000 is to use the name of the scope colon colon and then the thing you wanted to get 515 00:24:06,000 --> 00:24:07,000 out - 516 00:24:07,000 --> 00:24:11,000 you were trying to find, trying to use. 517 00:24:11,000 --> 00:24:14,000 So when we're defining all these member functions, we're saying, ''It's the times set 518 00:24:14,000 --> 00:24:18,000 hour member function that I'm writing, not just a function called set hour.'' 519 00:24:18,000 --> 00:24:20,000 If I leave this off, 520 00:24:20,000 --> 00:24:23,000 I have a function that says, ''Boy, its set hour N to new value.'' 521 00:24:23,000 --> 00:24:26,000 What the compiler thinks I'm writing there is just an ordinary global 522 00:24:26,000 --> 00:24:27,000 function. 523 00:24:27,000 --> 00:24:31,000 It thinks there's a global function, just name this set hour. It takes one primary to reach its end, 524 00:24:31,000 --> 00:24:34,000 and it returns to void. It doesn't think it has anything to do with the time class, 525 00:24:34,000 --> 00:24:37,000 and the next thing it will notice is in here, 526 00:24:37,000 --> 00:24:41,000 when I'm trying to access features that are relevant to time, it will start giving me compiler 527 00:24:41,000 --> 00:24:43,000 errors. It'll say, ''Hour? Where did hour come from? 528 00:24:43,000 --> 00:24:46,000 I know about new value. It's a [inaudible]. But hour just came out of nowhere. That was completely 529 00:24:46,000 --> 00:24:50,000 undeclared to me. Something must be wrong.'' 530 00:24:50,000 --> 00:24:51,000 So if we - 531 00:24:51,000 --> 00:24:54,000 that's a mistake you will certainly make at least once, 532 00:24:54,000 --> 00:24:55,000 and we'll want 533 00:24:55,000 --> 00:25:00,000 to commit to being attentive about. It's like it is the time set hour. It is the times 534 00:25:00,000 --> 00:25:01,000 two string. 535 00:25:01,000 --> 00:25:05,000 And that is distinguished from other functions of that same name. 536 00:25:05,000 --> 00:25:08,000 That actually is kind of a neat little feature - the fact that that worked 537 00:25:08,000 --> 00:25:12,000 that way [inaudible]. The member function side shows up in a lot of our classes on vector, on stack, 538 00:25:12,000 --> 00:25:15,000 on string, on map - 539 00:25:15,000 --> 00:25:18,000 that the idea that all of those things can be called size is actually really handy 540 00:25:18,000 --> 00:25:22,000 because who wants to remember that one of them's length and one of them's size and one of them's numb entries 541 00:25:22,000 --> 00:25:23,000 and one of them's depth 542 00:25:23,000 --> 00:25:25,000 and one of them's length or something. 543 00:25:25,000 --> 00:25:29,000 That - having them all be size means that you have this one name you use when you 544 00:25:29,000 --> 00:25:31,000 want to get the information about how big a collection is. 545 00:25:31,000 --> 00:25:34,000 And the fact that the compiler can keep them all straight is based on this 546 00:25:34,000 --> 00:25:36,000 scoping mechanism. 547 00:25:36,000 --> 00:25:37,000 There's a 548 00:25:37,000 --> 00:25:39,000 vector size, which is different than stack size, which is different than map 549 00:25:39,000 --> 00:25:43,000 size, and it doesn't confuse them up because it has this scoping 550 00:25:43,000 --> 00:25:49,000 to keep them all straight. 551 00:25:49,000 --> 00:25:53,000 So when we're writing the implementation of our member functions, 552 00:25:53,000 --> 00:25:55,000 there's a couple things, right? That we need to know about how to make them work 553 00:25:55,000 --> 00:25:57,000 the way they're supposed to. 554 00:25:57,000 --> 00:26:01,000 So in the time member function like shift by, 555 00:26:01,000 --> 00:26:05,000 that if we just refer to the field hour or minute - one of the data members of a 556 00:26:05,000 --> 00:26:06,000 time object, it 557 00:26:06,000 --> 00:26:07,000 is assumed 558 00:26:07,000 --> 00:26:11,000 that the hour or minute we're talking about is of the receiver. So 559 00:26:11,000 --> 00:26:14,000 shift by is never called without a receiver. 560 00:26:14,000 --> 00:26:18,000 There is not mechanism that lets you just call shift by without something in front 561 00:26:18,000 --> 00:26:18,000 of it. 562 00:26:18,000 --> 00:26:22,000 So shift by got called - there's some time object somewhere where it says t.shiftby an 563 00:26:22,000 --> 00:26:24,000 hour and 15 minutes that moves that - 564 00:26:24,000 --> 00:26:26,000 the T time 565 00:26:26,000 --> 00:26:29,000 forward by that amount of hour and minute change. 566 00:26:29,000 --> 00:26:33,000 So in the context of shift by, you can count on 567 00:26:33,000 --> 00:26:35,000 that hour and minute refer to 568 00:26:35,000 --> 00:26:38,000 the fields of a receiving time object that currently has some value in 569 00:26:38,000 --> 00:26:39,000 the hour and minute 570 00:26:39,000 --> 00:26:42,000 that we're changing by some delta 571 00:26:42,000 --> 00:26:46,000 to move it forward. So any reference to the hour and minute fields with no other 572 00:26:46,000 --> 00:26:50,000 qualifying marks means my hour, my minute - the 573 00:26:50,000 --> 00:26:54,000 one that got the message. 574 00:26:54,000 --> 00:26:55,000 In the body of the 575 00:26:55,000 --> 00:26:56,000 member function, 576 00:26:56,000 --> 00:27:01,000 we also - so we can directly access these fields. We can also make further 577 00:27:01,000 --> 00:27:03,000 calls to other member functions. 578 00:27:03,000 --> 00:27:06,000 If there is a set hour and a set minute 579 00:27:06,000 --> 00:27:09,000 setter that are available on the time object, 580 00:27:09,000 --> 00:27:10,000 then we can say, 581 00:27:10,000 --> 00:27:14,000 ''Set hour, hour plus D - hour - the minute plus D minute, 582 00:27:14,000 --> 00:27:17,000 and then that will go through our own setter to update the hour and minute field 583 00:27:17,000 --> 00:27:19,000 to the new values. 584 00:27:19,000 --> 00:27:22,000 So this is a case where you're seeing a call to a member function without an 585 00:27:22,000 --> 00:27:24,000 explicit receiver, 586 00:27:24,000 --> 00:27:28,000 and in this case, the receiver is assumed to be the same receiver who originally 587 00:27:28,000 --> 00:27:31,000 got the shift by message. So this really isn't dropping the receiver or losing it, 588 00:27:31,000 --> 00:27:33,000 it's actually just assuming that, 589 00:27:33,000 --> 00:27:35,000 without any other 590 00:27:35,000 --> 00:27:37,000 explicit receiver, that it means me. 591 00:27:37,000 --> 00:27:39,000 So the time object that was asked to shift 592 00:27:39,000 --> 00:27:44,000 tells itself to change the hour and change the minute. 593 00:27:44,000 --> 00:27:48,000 We're gonna talk a little bit about why that might be an important strategy relative to the 594 00:27:48,000 --> 00:27:49,000 alternative here, but 595 00:27:49,000 --> 00:27:51,000 just to know that mechanically, they both work. 596 00:27:51,000 --> 00:27:55,000 And then the last thing [inaudible] is this secret variable - this idea that it 597 00:27:55,000 --> 00:27:57,000 knows who the receiver is and 598 00:27:57,000 --> 00:28:01,000 that it's actually using it as part of the access for the hour and the minute and the caller - that 599 00:28:01,000 --> 00:28:04,000 there actually is a way to explicitly access that syntax if you wanna know. 600 00:28:04,000 --> 00:28:08,000 There is a special variable called this 601 00:28:08,000 --> 00:28:11,000 that is only valid within the member function of 602 00:28:11,000 --> 00:28:13,000 603 00:28:13,000 --> 00:28:17,000 some class - any class. This is a pointer toward the receiver object. 604 00:28:17,000 --> 00:28:18,000 So this, 605 00:28:18,000 --> 00:28:21,000 in a time member function, is a time pointer. 606 00:28:21,000 --> 00:28:24,000 Now in a stack, it would be a stack pointer, and so on. 607 00:28:24,000 --> 00:28:27,000 And I can use the longhand form of this arrow hour 608 00:28:27,000 --> 00:28:29,000 to mean take the time 609 00:28:29,000 --> 00:28:33,000 this - do you reference it to get to the time object and access its hour field. 610 00:28:33,000 --> 00:28:35,000 [Inaudible] this arrow 611 00:28:35,000 --> 00:28:39,000 is doing the dereference and then sending itself the member function. 612 00:28:39,000 --> 00:28:42,000 This is equivalent, right? To dropping that entirely. 613 00:28:42,000 --> 00:28:47,000 So you will rarely see a C++ program where you use this longhand form. 614 00:28:47,000 --> 00:28:48,000 But it is 615 00:28:48,000 --> 00:28:51,000 the mechanism behind it 616 00:28:51,000 --> 00:28:54,000 - you can see explicitly in situations where 617 00:28:54,000 --> 00:28:56,000 you might wanna be very clear about it. 618 00:28:56,000 --> 00:28:59,000 Sometimes you'll use that. For example, when you have two time objects, and you're trying to compare 619 00:28:59,000 --> 00:29:02,000 them, you wanna be distinguishing the parameter from this. You might 620 00:29:02,000 --> 00:29:07,000 explicitly say, ''This hour - if this hour equals other hour.'' 621 00:29:07,000 --> 00:29:09,000 You might wanna make that clear which one you're talking about rather than 622 00:29:09,000 --> 00:29:13,000 dropping it in that situation. Any 623 00:29:13,000 --> 00:29:19,000 questions about a little bit mechanics? 624 00:29:19,000 --> 00:29:22,000 So I said that I would talk a little bit about, ''Well, why 625 00:29:22,000 --> 00:29:24,000 might you want to 626 00:29:24,000 --> 00:29:26,000 have your member functions just make calls to other member functions rather 627 00:29:26,000 --> 00:29:29,000 than directly modify those fields?'' 628 00:29:29,000 --> 00:29:32,000 And one of the advantages, right? Of that object sorting programming is that you can 629 00:29:32,000 --> 00:29:35,000 actually really be very tightly 630 00:29:35,000 --> 00:29:37,000 managing the object's state 631 00:29:37,000 --> 00:29:40,000 and trying to make sure that the object never gets inconsistent. For example, if 632 00:29:40,000 --> 00:29:44,000 you're a stack, you wanna be sure that if you think the depth of the stack is 633 00:29:44,000 --> 00:29:46,000 ten, that there are ten valid elements. You never wanna get in a situation where somehow you 634 00:29:46,000 --> 00:29:49,000 think there are eight, but really there are ten or vice versa. It's your job to make sure 635 00:29:49,000 --> 00:29:50,000 that it makes sense. 636 00:29:50,000 --> 00:29:53,000 In the case of time, there's actually kind of a lot of 637 00:29:53,000 --> 00:29:57,000 invalid or illegal time values that you can imagine sneaking into your system 638 00:29:57,000 --> 00:29:59,000 where suddenly, you have the time 639 00:29:59,000 --> 00:30:01,000 - 55 negative 14. 640 00:30:01,000 --> 00:30:04,000 Right? You wanna be sure that the hour and minute really make sense for what you 641 00:30:04,000 --> 00:30:06,000 know to be the domain of valid times. 642 00:30:06,000 --> 00:30:09,000 By having the instance variables be private - 643 00:30:09,000 --> 00:30:13,000 the data members - nobody can muck with them other than you and the implementation. 644 00:30:13,000 --> 00:30:17,000 And so if you actually are very disciplined about making sure they can't ever get 645 00:30:17,000 --> 00:30:18,000 wrong - 646 00:30:18,000 --> 00:30:20,000 that no matter what operations you offer - 647 00:30:20,000 --> 00:30:23,000 shifting it forward, shifting it back, 648 00:30:23,000 --> 00:30:25,000 resetting it to new values - 649 00:30:25,000 --> 00:30:29,000 you make sure that there's no way a bad value could creep in. And probably the easiest way to 650 00:30:29,000 --> 00:30:34,000 do that is to build a gatekeeper - is to have there be one central point 651 00:30:34,000 --> 00:30:35,000 where you change hour, 652 00:30:35,000 --> 00:30:39,000 and everything goes through that one central point. And that central point is designed to make 653 00:30:39,000 --> 00:30:39,000 sure that 654 00:30:39,000 --> 00:30:42,000 nothing can sneak past it. 655 00:30:42,000 --> 00:30:46,000 So if somebody tries to change the hour to something that's not between 1 and 656 00:30:46,000 --> 00:30:47,000 12, 657 00:30:47,000 --> 00:30:49,000 you can just decide to bound it. 658 00:30:49,000 --> 00:30:51,000 This may not be the right thing to do. Maybe I should raise an error, but 659 00:30:51,000 --> 00:30:55,000 at the very least, I need to do something if they give me negative 660 00:30:55,000 --> 00:30:56,000 14 or 661 00:30:56,000 --> 00:30:57,000 82. And 662 00:30:57,000 --> 00:31:00,000 so right now, I choose to say, ''Well, I'll just bring it to the closest value that's in 663 00:31:00,000 --> 00:31:02,000 range.'' 664 00:31:02,000 --> 00:31:04,000 An error would be a completely valid alternative. 665 00:31:04,000 --> 00:31:07,000 Similarly, something about the minute - if they give me a minute that's not something between 666 00:31:07,000 --> 00:31:09,000 0 and 59, that 667 00:31:09,000 --> 00:31:12,000 doesn't make sense. And so I just [inaudible] it - just to take the 668 00:31:12,000 --> 00:31:14,000 lower order part of it. 669 00:31:14,000 --> 00:31:18,000 If - these are the only places - let's say, imagine all of the time class 670 00:31:18,000 --> 00:31:20,000 where I ever assign to hour and minute. 671 00:31:20,000 --> 00:31:22,000 And everywhere else where I wanna change it, 672 00:31:22,000 --> 00:31:26,000 I say, ''Well, here. Change it by this much and stick it through. Here's the 673 00:31:26,000 --> 00:31:30,000 value I'd like to set it to. Let me ask set hour to do it on my behalf - 674 00:31:30,000 --> 00:31:32,000 that if I've made some error in the calculation or I've been asked to do 675 00:31:32,000 --> 00:31:34,000 something kind of ridiculous 676 00:31:34,000 --> 00:31:35,000 that it will 677 00:31:35,000 --> 00:31:37,000 cause the right 678 00:31:37,000 --> 00:31:38,000 eventual 679 00:31:38,000 --> 00:31:39,000 assignment to be made.'' 680 00:31:39,000 --> 00:31:42,000 And so that's why I say, ''What's this advantage? Why would we wanna do this?'' It's about control, right? 681 00:31:42,000 --> 00:31:43,000 682 00:31:43,000 --> 00:31:47,000 Kind of centralizing the access and the robustness of your interface. Just 683 00:31:47,000 --> 00:31:50,000 say, ''Well, here at the one place wherever change it. 684 00:31:50,000 --> 00:31:51,000 Let's make sure everything 685 00:31:51,000 --> 00:31:55,000 goes through that same interface. And that way, there's no way you 686 00:31:55,000 --> 00:32:02,000 can sneak a - through some back door - a bad value in.'' 687 00:32:02,000 --> 00:32:05,000 So a couple other things you need to know about class mechanics. 688 00:32:05,000 --> 00:32:07,000 There are a few special member functions. 689 00:32:07,000 --> 00:32:09,000 One is the constructor. 690 00:32:09,000 --> 00:32:11,000 So the constructor is 691 00:32:11,000 --> 00:32:14,000 a part - it's just automatically tied in with allocation - 692 00:32:14,000 --> 00:32:18,000 that when you allocate an object - either with new or on the stack - 693 00:32:18,000 --> 00:32:22,000 the constructor is automatically invoked as part of that process. And so that 694 00:32:22,000 --> 00:32:24,000 gives you your opportunity, if you define a constructor, 695 00:32:24,000 --> 00:32:27,000 to set up your data members the way you want. 696 00:32:27,000 --> 00:32:31,000 If you don't specify a constructor, you get the default constructor. 697 00:32:31,000 --> 00:32:34,000 The default constructor takes no arguments and basically does nothing to 698 00:32:34,000 --> 00:32:36,000 your arguments. So it leaves them uninitialized. 699 00:32:36,000 --> 00:32:39,000 So for most things, that's not gonna be appropriate. It's probably the first thing you wanna 700 00:32:39,000 --> 00:32:42,000 do when you make a class is to write a constructor that sets yourself into a 701 00:32:42,000 --> 00:32:44,000 known, good state. 702 00:32:44,000 --> 00:32:47,000 It has a special prototype. It has to have exactly the same name as the class. It has 703 00:32:47,000 --> 00:32:51,000 no return type - not void, not anything. So it looks a little strange when you first 704 00:32:51,000 --> 00:32:52,000 see it. 705 00:32:52,000 --> 00:32:54,000 And then it can have parameters if you need them. 706 00:32:54,000 --> 00:32:58,000 It also can be overloaded. If you want more than one 707 00:32:58,000 --> 00:32:59,000 constructor, you can have 708 00:32:59,000 --> 00:33:01,000 multiple of them. 709 00:33:01,000 --> 00:33:04,000 So if I were to add one to my time class, 710 00:33:04,000 --> 00:33:07,000 I put in a function you notice has no return type, right? So the first thing you're 711 00:33:07,000 --> 00:33:09,000 seeing is the name of the 712 00:33:09,000 --> 00:33:13,000 constructor, which has to exactly match the case and name of the class itself - 713 00:33:13,000 --> 00:33:14,000 time. And 714 00:33:14,000 --> 00:33:17,000 in this case, choosing to make a constructor that takes two integer arguments - 715 00:33:17,000 --> 00:33:20,000 the starting hour and minute 716 00:33:20,000 --> 00:33:22,000 that I want. 717 00:33:22,000 --> 00:33:23,000 In the CPP, 718 00:33:23,000 --> 00:33:26,000 right? The implementation of the constructor - 719 00:33:26,000 --> 00:33:30,000 time - within the scope of the time class - time colon colon time - again, no return type 720 00:33:30,000 --> 00:33:31,000 here - 721 00:33:31,000 --> 00:33:32,000 taking the hour and minute and setting it. 722 00:33:32,000 --> 00:33:36,000 I can actually make calls to my member functions, and given my earlier little 723 00:33:36,000 --> 00:33:40,000 speech about this, it seems like it would be even better, for example, to be calling set hour 724 00:33:40,000 --> 00:33:40,000 of 725 00:33:40,000 --> 00:33:43,000 HR and set minute of MIN 726 00:33:43,000 --> 00:33:46,000 to just make sure that even if they give me initial values that are total 727 00:33:46,000 --> 00:33:46,000 garbage, 728 00:33:46,000 --> 00:33:49,000 right? That I don't let the time start off with some 729 00:33:49,000 --> 00:33:51,000 negative 45 730 00:33:51,000 --> 00:33:55,000 - 100 - kind of state that doesn't make sense. 731 00:33:55,000 --> 00:33:57,000 Once this constructor is in place, 732 00:33:57,000 --> 00:34:01,000 right? Then the calls to create a time 733 00:34:01,000 --> 00:34:04,000 will show two arguments are required to 734 00:34:04,000 --> 00:34:08,000 construct a time that's - to specify the hour and minutes is no longer optional, 735 00:34:08,000 --> 00:34:11,000 whereas prior to having a constructor that was a default constructor - the default 736 00:34:11,000 --> 00:34:13,000 constructor took no arguments. 737 00:34:13,000 --> 00:34:18,000 Once you declare any constructors, the compiler stops giving you anything for free. 738 00:34:18,000 --> 00:34:22,000 And so if you want both the default constructor and another several argument 739 00:34:22,000 --> 00:34:24,000 constructor, you'll just make several of them. You can have a time here that just says, 740 00:34:24,000 --> 00:34:26,000 ''Time, open [inaudible] close [inaudible],'' 741 00:34:26,000 --> 00:34:30,000 and then have a time colon colon time open [inaudible] close [inaudible] and set the hour and minute to 742 00:34:30,000 --> 00:34:33,000 sub default of 12:00 or whatever you want it. 743 00:34:33,000 --> 00:34:36,000 You can have as many constructors as you need, 744 00:34:36,000 --> 00:34:38,000 but typically, I would say most classes have one or two 745 00:34:38,000 --> 00:34:46,000 if not that many starting configurations you need to support typically. 746 00:34:46,000 --> 00:34:50,000 So something that's new to you, if you're coming from the Java world, the 747 00:34:50,000 --> 00:34:53,000 idea that there's a corresponding parallel function 748 00:34:53,000 --> 00:34:57,000 that is tied into deallocation 749 00:34:57,000 --> 00:35:01,000 that when an object is going away - the two times when an object is going away. One is 750 00:35:01,000 --> 00:35:04,000 when it's leaving scope for a stack allocated object. So if you have time T declared in 751 00:35:04,000 --> 00:35:08,000 some foreloop, and when you exit the foreloop, it automatically deallocates 752 00:35:08,000 --> 00:35:11,000 that object or destructs it. [Inaudible]. 753 00:35:11,000 --> 00:35:15,000 If you have new - that object new time out in the heap that when you delete that 754 00:35:15,000 --> 00:35:19,000 time object as part of the deallocation of memory, it will destruct 755 00:35:19,000 --> 00:35:22,000 it. So what it does is it calls the destructor when that happens. 756 00:35:22,000 --> 00:35:25,000 The destructor is your hook for, ''I need to clean up 757 00:35:25,000 --> 00:35:28,000 when this object is going away.'' 758 00:35:28,000 --> 00:35:32,000 It has the same name as the class, but prefix with a tilde. So tilde time is 759 00:35:32,000 --> 00:35:35,000 the destructor for the time class. 760 00:35:35,000 --> 00:35:40,000 It can never have any parameters, and it never has any return type. So 761 00:35:40,000 --> 00:35:43,000 time is the constructor name. Tilde time is the destructor's name. 762 00:35:43,000 --> 00:35:48,000 You don't always need a destructor. It's actually a little bit more unusual 763 00:35:48,000 --> 00:35:50,000 with some simple classes that - 764 00:35:50,000 --> 00:35:53,000 what you would need it for is if there were something that you did 765 00:35:53,000 --> 00:35:56,000 as part of constructing or building the object that you needed to clean up. 766 00:35:56,000 --> 00:35:59,000 And the most common need for that is you have dynamically allocated some 767 00:35:59,000 --> 00:36:00,000 members. 768 00:36:00,000 --> 00:36:01,000 So you have 769 00:36:01,000 --> 00:36:05,000 an object that holds onto a link list and has just a pointer to the head note 770 00:36:05,000 --> 00:36:06,000 and the bunch of cells that follow it 771 00:36:06,000 --> 00:36:08,000 that when you were destructing, 772 00:36:08,000 --> 00:36:11,000 you would wanna go trace that link list down and delete all those cells if 773 00:36:11,000 --> 00:36:14,000 you were gonna clean up after yourself. 774 00:36:14,000 --> 00:36:16,000 If you don't do that, you don't have a destructor, right? Then the pointers just 775 00:36:16,000 --> 00:36:20,000 get [inaudible], and all that memory is just hanging out there, clouding your heap. 776 00:36:20,000 --> 00:36:23,000 Sometimes there are things about opening files - like maybe you have a bunch of 777 00:36:23,000 --> 00:36:24,000 buffered output that you wanna 778 00:36:24,000 --> 00:36:27,000 be sure got committed to disc or a network connection you wanna close or 779 00:36:27,000 --> 00:36:31,000 something like that - so things that are open that you need to release. So 780 00:36:31,000 --> 00:36:33,000 typically, it's like resources that you need to 781 00:36:33,000 --> 00:36:34,000 clean up around that 782 00:36:34,000 --> 00:36:38,000 goes in the destructor. For the time class, there'd be no need, right? We have just 783 00:36:38,000 --> 00:36:41,000 simple integer variables. There's nothing special about them. So we don't 784 00:36:41,000 --> 00:36:43,000 actually need to go build 785 00:36:43,000 --> 00:36:45,000 a destructor. But 786 00:36:45,000 --> 00:36:52,000 some of the classes we'll see later will have a reason for that. 787 00:36:52,000 --> 00:36:54,000 So this idea of 788 00:36:54,000 --> 00:36:55,000 object design is 789 00:36:55,000 --> 00:36:59,000 sort of one of the more important points to think about when you're setting up 790 00:36:59,000 --> 00:37:00,000 and building an object, right? 791 00:37:00,000 --> 00:37:03,000 Is it's your responsibility to make an object that kind of does what it says 792 00:37:03,000 --> 00:37:08,000 it's gonna do and tries it's best to be robust in the face of all situations. 793 00:37:08,000 --> 00:37:11,000 Even in this case that, maybe, the client uses it incorrectly, 794 00:37:11,000 --> 00:37:15,000 that the point of this sort of programming is - it's not to think that 795 00:37:15,000 --> 00:37:18,000 we're probing among enemies or we're malicious, but it is people make mistakes, right? 796 00:37:18,000 --> 00:37:21,000 People accidentally have the time, and they changed it to something that doesn't make 797 00:37:21,000 --> 00:37:24,000 sense, or they do the calculation incorrectly or they access off the end of the vector - 798 00:37:24,000 --> 00:37:27,000 that having the response to that by your object be 799 00:37:27,000 --> 00:37:31,000 to crash or to just produce incorrect information or to return an erroneous 800 00:37:31,000 --> 00:37:32,000 result 801 00:37:32,000 --> 00:37:35,000 - is really not doing the best you can. 802 00:37:35,000 --> 00:37:38,000 So part of your goal in designing this object is just to build something that 803 00:37:38,000 --> 00:37:39,000 really 804 00:37:39,000 --> 00:37:43,000 is a lovely work of art that does exactly what you want and catches all 805 00:37:43,000 --> 00:37:46,000 the mistakes, and even things that are really just the client's fault, right? 806 00:37:46,000 --> 00:37:48,000 Asking you to do irrational things 807 00:37:48,000 --> 00:37:50,000 are handled gracefully. 808 00:37:50,000 --> 00:37:52,000 And so part of that is really taking kind of 809 00:37:52,000 --> 00:37:56,000 a big picture view of all the operations on the class and making sure 810 00:37:56,000 --> 00:37:59,000 that you have published the operations that are 811 00:37:59,000 --> 00:37:59,000 appropriate, 812 00:37:59,000 --> 00:38:03,000 right? That they respond to all forms of input gracefully, 813 00:38:03,000 --> 00:38:07,000 and that they kind of manage the object's state as it moves through the different 814 00:38:07,000 --> 00:38:09,000 operations in a way that's consistent. 815 00:38:09,000 --> 00:38:12,000 And so part of that, right? Is thinking about, ''Well, who accesses the data where?'' 816 00:38:12,000 --> 00:38:16,000 And making sure that those accesses are really understood and controlled. Never 817 00:38:16,000 --> 00:38:20,000 having any public data members - once you have a public data member, all bets are off. 818 00:38:20,000 --> 00:38:22,000 If hour and minute are public, 819 00:38:22,000 --> 00:38:25,000 anybody, anywhere, anytime can just reach in and change it to whatever they want. 820 00:38:25,000 --> 00:38:28,000 All guarantees are lost. So you would never want to do that, right? You 821 00:38:28,000 --> 00:38:30,000 are exposing part of your 822 00:38:30,000 --> 00:38:32,000 internals, right? For everyone to see. It's like having the door on the back of the microwave - you 823 00:38:32,000 --> 00:38:37,000 just open it up and you can start, like, rewiring. It's like - that's not gonna end well. You 824 00:38:37,000 --> 00:38:38,000 correctly 825 00:38:38,000 --> 00:38:42,000 initialized all your members in your constructor, and then you 826 00:38:42,000 --> 00:38:44,000 consider where and when 827 00:38:44,000 --> 00:38:47,000 to allow access to directly modify those things if - like through a 828 00:38:47,000 --> 00:38:49,000 setter - if it's needed and if it 829 00:38:49,000 --> 00:38:51,000 is properly 830 00:38:51,000 --> 00:38:52,000 constrained. 831 00:38:52,000 --> 00:38:56,000 The other thing that's an important part of kind of designing the interface is making 832 00:38:56,000 --> 00:38:58,000 sure that the object [inaudible] is fully formed. 833 00:38:58,000 --> 00:39:00,000 That it does all the things you'd like it to do 834 00:39:00,000 --> 00:39:04,000 and kind of simplifies the client's use of it as opposed to kind of going half 835 00:39:04,000 --> 00:39:07,000 the job and then leading them to have to do a bunch of other things. It 836 00:39:07,000 --> 00:39:11,000 has a complete kind of coherent set of applications. 837 00:39:11,000 --> 00:39:13,000 So if you needed to print a time 838 00:39:13,000 --> 00:39:16,000 that one way, you could supply those. You can say, ''Well, you can get the hour. You 839 00:39:16,000 --> 00:39:17,000 can get the minute. 840 00:39:17,000 --> 00:39:20,000 And you can convert them to string. And you can put a colon in the middle of them. And then you 841 00:39:20,000 --> 00:39:21,000 can print it. 842 00:39:21,000 --> 00:39:25,000 Why bother me about it? Like, you wanna print time? That's your business.'' 843 00:39:25,000 --> 00:39:28,000 On the other hand, right? Printing seems like a pretty fundamental operation that would 844 00:39:28,000 --> 00:39:29,000 just be nice for time to support. 845 00:39:29,000 --> 00:39:32,000 Maybe it supports it by having just a print method. Maybe it supports it by 846 00:39:32,000 --> 00:39:36,000 giving you a string form like two string where it does those calculations - it 847 00:39:36,000 --> 00:39:38,000 converts it and gives it back to you, 848 00:39:38,000 --> 00:39:41,000 and then you can decide to just output it as a string. 849 00:39:41,000 --> 00:39:45,000 But having that be a part of the class really makes the client's job just easier. They're 850 00:39:45,000 --> 00:39:48,000 likely to need something like that. Why make everybody who uses your time 851 00:39:48,000 --> 00:39:51,000 class have to reproduce this functionality that really feels like something the 852 00:39:51,000 --> 00:39:53,000 time class itself should support? 853 00:39:53,000 --> 00:39:56,000 And so when you think about your set of operations, you have some lists you might 854 00:39:56,000 --> 00:39:59,000 need in the near future. You're also trying to think a little bit more big picture 855 00:39:59,000 --> 00:40:03,000 about what - well, in all the situations you use times, what kind of operations come out as being 856 00:40:03,000 --> 00:40:04,000 useful. 857 00:40:04,000 --> 00:40:06,000 While I'm implementing time, why don't I just kinda build 858 00:40:06,000 --> 00:40:09,000 the full-fledge version 859 00:40:09,000 --> 00:40:12,000 that has the functionality for the things I imagine to be likely to be 860 00:40:12,000 --> 00:40:13,000 needed. 861 00:40:13,000 --> 00:40:15,000 So comparing, right? 862 00:40:15,000 --> 00:40:18,000 Two times - is this is one before this one? Are they equal? Right? Moving them around - 863 00:40:18,000 --> 00:40:19,000 just 864 00:40:19,000 --> 00:40:24,000 kinda giving you the whole package. So here's a little 865 00:40:24,000 --> 00:40:26,000 thought about what 866 00:40:26,000 --> 00:40:29,000 are the advantages, right? Of the 867 00:40:29,000 --> 00:40:33,000 object to design or object in capsulation means that 868 00:40:33,000 --> 00:40:36,000 you have described what time does. 869 00:40:36,000 --> 00:40:39,000 You say it allows you to set the hour. You have described that it'll compare them to 870 00:40:39,000 --> 00:40:42,000 see if one's less than another. You have a two string 871 00:40:42,000 --> 00:40:43,000 or a shift by, 872 00:40:43,000 --> 00:40:48,000 but you have made no guarantees to them about what you really do - how you really 873 00:40:48,000 --> 00:40:49,000 internally work it. 874 00:40:49,000 --> 00:40:52,000 The time interface might describe things, like, in terms of hour and minute. ''Oh, it's an 875 00:40:52,000 --> 00:40:56,000 hour and a minute in time, and you can shift it by hours and minutes. You can ask 876 00:40:56,000 --> 00:40:57,000 me for the hour and the minute.'' 877 00:40:57,000 --> 00:41:02,000 But internally, there's no rule that says - because our interface is hour and minute - 878 00:41:02,000 --> 00:41:06,000 that we have to have fields called hour and fields called minute. That in fact 879 00:41:06,000 --> 00:41:10,000 manipulating it, right? As hour and minute is messy. And if you throw in a.m./p.m., 880 00:41:10,000 --> 00:41:12,000 it's even worse. 881 00:41:12,000 --> 00:41:15,000 That all the things, like, people decide if one time is less than another - it's like, ''Well, 882 00:41:15,000 --> 00:41:18,000 if this one's a.m. and that one's p.m., then it's less than.'' Right? 883 00:41:18,000 --> 00:41:22,000 And if they're both a.m. or p.m., right? Then we start looking at the hour. And if the 884 00:41:22,000 --> 00:41:26,000 hour's the same, we start looking at the minute. Like, it just doesn't - it gets goopy. Right? 885 00:41:26,000 --> 00:41:30,000 We can make it work, but 886 00:41:30,000 --> 00:41:32,000 why do it if we don't have to? 887 00:41:32,000 --> 00:41:35,000 So if we just, instead, 888 00:41:35,000 --> 00:41:38,000 pick a different representation - it's our internals. Nobody needs to know what 889 00:41:38,000 --> 00:41:40,000 we're doing. 890 00:41:40,000 --> 00:41:43,000 It's like, ''I don't wanna keep track of hour and minute. Hour and minute is some 891 00:41:43,000 --> 00:41:47,000 other artificial sort of human representation.'' Computers are really good at 892 00:41:47,000 --> 00:41:51,000 much more simple things, like what if I just said, ''Look. Every day - every minute 893 00:41:51,000 --> 00:41:52,000 within the day 894 00:41:52,000 --> 00:41:55,000 is assigned a number: zero is midnight, right? 895 00:41:55,000 --> 00:41:56,000 And then 896 00:41:56,000 --> 00:41:58,000 720, right? 897 00:41:58,000 --> 00:42:00,000 Is noon.'' 898 00:42:00,000 --> 00:42:02,000 And just whatever. You just - you said, ''Minutes since midnight.'' 899 00:42:02,000 --> 00:42:06,000 Two minutes into midnight is 12:02. Right? Twelve minutes is 900 00:42:06,000 --> 00:42:09,000 12:10. Sixty minutes is 1:00 a.m. Right? 901 00:42:09,000 --> 00:42:13,000 I just mark everything down there. Then it turns out, right? A lot of my operations become 902 00:42:13,000 --> 00:42:14,000 really easy. 903 00:42:14,000 --> 00:42:17,000 I wanna see if this time is less than the other? It's like, ''Okay. Just 904 00:42:17,000 --> 00:42:19,000 compare their two minutes since midnight.'' 905 00:42:19,000 --> 00:42:23,000 I wanna move a time 60 minutes forward? Well, I just add 60 minutes to whatever 906 00:42:23,000 --> 00:42:24,000 number I have. 907 00:42:24,000 --> 00:42:28,000 You can do the wraparound really easily. So like, if you were close to the end of the day 908 00:42:28,000 --> 00:42:32,000 at 11:30, and you add an hour. Right? It's very easy to just use [inaudible] to wrap you 909 00:42:32,000 --> 00:42:34,000 back around to the 12:30. 910 00:42:34,000 --> 00:42:37,000 But if you're doing it with hours and minutes and a.m./p.m., all those things are 911 00:42:37,000 --> 00:42:40,000 very ugly. 912 00:42:40,000 --> 00:42:44,000 So the thing is we can still describe our interfaces hours and minutes because that's how 913 00:42:44,000 --> 00:42:45,000 clients want to see it. 914 00:42:45,000 --> 00:42:48,000 But internally, we get to make all the decisions we want, and we might as well make the ones 915 00:42:48,000 --> 00:42:51,000 that make our lives easier - make it easier to get the code right. 916 00:42:51,000 --> 00:42:55,000 It's actually - it takes less time to do the operations right. It'll 917 00:42:55,000 --> 00:42:56,000 run more efficiently. 918 00:42:56,000 --> 00:42:59,000 It uses less space, in fact. And 919 00:42:59,000 --> 00:43:01,000 it just made everything easier from our point of view. 920 00:43:01,000 --> 00:43:04,000 And it turns out we can still have operators - like set hour and get hour 921 00:43:04,000 --> 00:43:06,000 and set minute and get minute, right? 922 00:43:06,000 --> 00:43:10,000 They just internally kinda convert to the internal representation. But they 923 00:43:10,000 --> 00:43:13,000 provide an interface, right? That seems appropriate for the client. It doesn't mean it 924 00:43:13,000 --> 00:43:14,000 has to 925 00:43:14,000 --> 00:43:16,000 match what we do inside. 926 00:43:16,000 --> 00:43:18,000 So that's actually kind of a really neat - a 927 00:43:18,000 --> 00:43:21,000 neat thing to keep in mind, right? Is that that's part of what we bought - is 928 00:43:21,000 --> 00:43:22,000 that 929 00:43:22,000 --> 00:43:25,000 they don't actually have any guarantee about how we implemented it, and we're not 930 00:43:25,000 --> 00:43:27,000 gonna tell them. 931 00:43:27,000 --> 00:43:29,000 So I will 932 00:43:29,000 --> 00:43:31,000 leave you with this thought about 933 00:43:31,000 --> 00:43:36,000 abstraction because that is sort of a key advantage of working this way, right? 934 00:43:36,000 --> 00:43:38,000 Is there really is a wall 935 00:43:38,000 --> 00:43:41,000 between the client and the implementer 936 00:43:41,000 --> 00:43:44,000 that is an important part of - it feels like a restriction. It feels like a 937 00:43:44,000 --> 00:43:47,000 jail. It feels like a prison if you think about it that way. But in fact, it's 938 00:43:47,000 --> 00:43:49,000 liberating. It means we're not in each other's hair. 939 00:43:49,000 --> 00:43:54,000 We're not dependent on each other in any meaningful way. We have this little, tiny conduit - 940 00:43:54,000 --> 00:43:56,000 that chink in the wall we call the interface - 941 00:43:56,000 --> 00:43:59,000 that describes what things we both can depend on. 942 00:43:59,000 --> 00:44:02,000 But then everything else is at the liberty of the person who's on 943 00:44:02,000 --> 00:44:04,000 their side of the wall to do what they want 944 00:44:04,000 --> 00:44:08,000 without regard to what the other person's expectations are. So 945 00:44:08,000 --> 00:44:11,000 we'll think about that in terms of, let's say, Lexicon and scanner and vector 946 00:44:11,000 --> 00:44:13,000 and all these kinda neat things on Friday 947 00:44:13,000 --> 00:44:16,000 to kinda dig around the backside and see what we've been missing out on. I 948 00:44:16,000 --> 00:44:21,000 will see you guys then.