1 00:00:00,000 --> 00:00:02,667 (upbeat music) 2 00:00:05,535 --> 00:00:07,605 A few videos back I mentioned that the way 3 00:00:07,605 --> 00:00:10,635 we were adding loot to the inventory wasn't a good idea. 4 00:00:10,635 --> 00:00:12,393 And in this video we're going to look at why 5 00:00:12,393 --> 00:00:14,815 that isn't a good idea and what we can do about it. 6 00:00:14,815 --> 00:00:16,271 We're going to start though by deleting 7 00:00:16,271 --> 00:00:18,755 the code we used for for loops 8 00:00:18,755 --> 00:00:21,099 and un-commenting our player code. 9 00:00:21,099 --> 00:00:24,585 So I'm just going to delete the for loop code 10 00:00:24,585 --> 00:00:27,845 and I'm going to select or delete the rest of it first. 11 00:00:27,845 --> 00:00:31,626 And select the rest of the code that was commented out. 12 00:00:31,626 --> 00:00:32,879 You can come up to the code menu 13 00:00:32,879 --> 00:00:36,426 and I can click on comment with live comment 14 00:00:36,426 --> 00:00:41,119 which un-does the changes if it was already commented at. 15 00:00:41,119 --> 00:00:43,294 And obviously these other things that were commented at, 16 00:00:43,294 --> 00:00:45,275 were things that were commented at previously, 17 00:00:45,275 --> 00:00:47,152 in case you're wondering why that's still 18 00:00:47,152 --> 00:00:48,459 sitting there and commented at. 19 00:00:48,459 --> 00:00:50,412 Okay, let's just run the programme 20 00:00:50,412 --> 00:00:52,745 and make sure that it works. 21 00:00:59,228 --> 00:01:01,770 Okay, we can see that we've got our code working again, 22 00:01:01,770 --> 00:01:03,325 everything's working nicely. 23 00:01:03,325 --> 00:01:05,415 So getting back to the problem at hand, 24 00:01:05,415 --> 00:01:08,049 why isn't it a good idea for our main function 25 00:01:08,049 --> 00:01:09,664 to add loot to Tim's inventory 26 00:01:09,664 --> 00:01:13,264 in this fashion that it's doing here. 27 00:01:13,264 --> 00:01:15,784 Well there's a couple reasons why it's not a good idea. 28 00:01:15,784 --> 00:01:18,622 One reason is that main shouldn't have to know 29 00:01:18,622 --> 00:01:21,987 that the players are using an array list to store the loot. 30 00:01:21,987 --> 00:01:24,297 So looking at our player class 31 00:01:24,297 --> 00:01:27,421 we've declared inventory to be an array list. 32 00:01:27,421 --> 00:01:29,579 Now we may decide to change that in the future 33 00:01:29,579 --> 00:01:31,851 to use some other kind of structure. 34 00:01:31,851 --> 00:01:35,896 Now if we do that, we might break the code in main. 35 00:01:35,896 --> 00:01:38,197 Our main function's expecting an array list 36 00:01:38,197 --> 00:01:40,823 with an add method that it can use. 37 00:01:40,823 --> 00:01:42,733 Now if we use something else, maybe a structure 38 00:01:42,733 --> 00:01:44,982 that has a pin function instead of add 39 00:01:44,982 --> 00:01:47,329 then the code in main would stop working. 40 00:01:47,329 --> 00:01:48,619 Now one of the principles 41 00:01:48,619 --> 00:01:52,256 of object oriented programming is encapsulation. 42 00:01:52,256 --> 00:01:54,347 So encapsulation here, basically means 43 00:01:54,347 --> 00:01:57,826 not exposing the inner workings of a class 44 00:01:57,826 --> 00:02:00,354 to code outside of that class. 45 00:02:00,354 --> 00:02:03,199 Now Kotlin takes a more relaxed attitude or approach 46 00:02:03,199 --> 00:02:05,334 to encapsulating class properties. 47 00:02:05,334 --> 00:02:07,697 Everything's public by default. 48 00:02:07,697 --> 00:02:09,235 Now that's why the main function 49 00:02:09,235 --> 00:02:12,043 can directly access inventory. 50 00:02:12,043 --> 00:02:14,337 Now if we want to encapsulate our inventory, 51 00:02:14,337 --> 00:02:16,699 we can mark it as private. 52 00:02:16,699 --> 00:02:19,507 So come up here to the definition on line seven 53 00:02:19,507 --> 00:02:23,755 and type private ahead of the val inventory 54 00:02:23,755 --> 00:02:26,291 and now nothing outside of the player class 55 00:02:26,291 --> 00:02:28,812 can access the inventory. 56 00:02:28,812 --> 00:02:31,996 Now by default Kotlin makes properties and functions public, 57 00:02:31,996 --> 00:02:35,105 which means that they're available to external code. 58 00:02:35,105 --> 00:02:38,116 Anything that creates an instance of our player class, 59 00:02:38,116 --> 00:02:41,897 for example, could access all it's properties and functions. 60 00:02:41,897 --> 00:02:44,705 Now you can find the documentation and visibility 61 00:02:44,705 --> 00:02:47,821 modifiers in Kotlin and I'm just gonna put the link, 62 00:02:47,821 --> 00:02:49,783 bring the link up into a browser. 63 00:02:49,783 --> 00:02:51,950 Have a quick look at that. 64 00:02:58,326 --> 00:03:00,688 Now I'm not actually going to go through this document. 65 00:03:00,688 --> 00:03:02,982 It can be quite confusing at the moment, 66 00:03:02,982 --> 00:03:06,091 but it's worth bookmarking this page for reference later. 67 00:03:06,091 --> 00:03:07,480 When you find some code that uses 68 00:03:07,480 --> 00:03:09,804 the internal modifier, for example, you can 69 00:03:09,804 --> 00:03:12,989 check back here to find out what that means. 70 00:03:12,989 --> 00:03:14,257 So scrolling down quickly, we'll get 71 00:03:14,257 --> 00:03:18,211 to the classes and interfaces section. 72 00:03:18,211 --> 00:03:19,139 You see that it's a description 73 00:03:19,139 --> 00:03:21,972 on the private modifier, up here. 74 00:03:22,807 --> 00:03:26,112 Means visible inside the class only, 75 00:03:26,112 --> 00:03:28,279 including all its members. 76 00:03:29,259 --> 00:03:32,163 So by marking the inventory properly as private, 77 00:03:32,163 --> 00:03:34,759 it's now no longer available to any code 78 00:03:34,759 --> 00:03:37,069 outside of the player class. 79 00:03:37,069 --> 00:03:38,208 Now of course that should mean 80 00:03:38,208 --> 00:03:39,929 that we've now broken main. 81 00:03:39,929 --> 00:03:42,596 So if I switch back to that now, 82 00:03:44,668 --> 00:03:47,241 you can see we've got some errors showing. 83 00:03:47,241 --> 00:03:51,158 So every time main tries to access a player's inventory 84 00:03:51,158 --> 00:03:53,362 Android Studio is showing an error. 85 00:03:53,362 --> 00:03:56,229 Now that's not good, but it's okay to get errors 86 00:03:56,229 --> 00:03:58,259 while you're still developing your classes. 87 00:03:58,259 --> 00:04:01,504 That's normal as you try things out and modify your design. 88 00:04:01,504 --> 00:04:03,670 What's not good though, is modifying a class 89 00:04:03,670 --> 00:04:07,043 once it's been used and breaking all the code that uses it. 90 00:04:07,043 --> 00:04:09,911 So that's one of the things we're trying to avoid here. 91 00:04:09,911 --> 00:04:13,216 Now if we don't want main or any other client code 92 00:04:13,216 --> 00:04:16,152 of our player class to access the inventory directly, 93 00:04:16,152 --> 00:04:18,182 then we need to provide a method for clients 94 00:04:18,182 --> 00:04:21,797 to call when they need to add things to the inventory. 95 00:04:21,797 --> 00:04:24,317 So I'm going to call that method or function 96 00:04:24,317 --> 00:04:27,532 get loot and that reflects what's happening 97 00:04:27,532 --> 00:04:30,355 when loot's added to a player's inventory. 98 00:04:30,355 --> 00:04:32,405 So let's go ahead and do that. 99 00:04:32,405 --> 00:04:33,915 Go back to the player class, 100 00:04:33,915 --> 00:04:38,027 we're going to add that below, the toString function. 101 00:04:38,027 --> 00:04:39,491 And again what we're doing is, we're creating 102 00:04:39,491 --> 00:04:41,778 a function for clients to call when they need 103 00:04:41,778 --> 00:04:44,332 to add things to the inventory. 104 00:04:44,332 --> 00:04:47,415 We'll start with fun, space, getloot 105 00:04:49,408 --> 00:04:51,241 (item 106 00:04:52,154 --> 00:04:52,987 :loot 107 00:04:56,582 --> 00:05:00,332 After {, it's going to be inventory.add item. 108 00:05:03,147 --> 00:05:06,038 So now that we've done that, we can go back to our main 109 00:05:06,038 --> 00:05:09,358 and we can change main to use the getloot function 110 00:05:09,358 --> 00:05:11,999 instead of accessing the inventory directly. 111 00:05:11,999 --> 00:05:15,199 So to do that we type, we select, 112 00:05:15,199 --> 00:05:16,866 we type tim.getloot. 113 00:05:28,284 --> 00:05:30,269 Those two changes there and then for the second one 114 00:05:30,269 --> 00:05:32,269 we do something similar. 115 00:05:33,982 --> 00:05:34,815 Getloot 116 00:05:43,631 --> 00:05:44,464 Getloot 117 00:05:47,685 --> 00:05:49,104 The right number of parentheses 118 00:05:49,104 --> 00:05:52,319 there to keep everything consistent and working okay. 119 00:05:52,319 --> 00:05:55,805 We've now changed it so that the main function 120 00:05:55,805 --> 00:05:58,303 is no longer accessing inventory directly. 121 00:05:58,303 --> 00:06:01,918 Rather it's doing it via the getloot function. 122 00:06:01,918 --> 00:06:02,846 Let's just run the programme 123 00:06:02,846 --> 00:06:06,763 to make sure everything works as it did before. 124 00:06:12,241 --> 00:06:15,388 And you can see we still got the same results when we run it 125 00:06:15,388 --> 00:06:17,184 but now though main doesn't know 126 00:06:17,184 --> 00:06:19,569 how the player class is storing the loot. 127 00:06:19,569 --> 00:06:22,339 So it can call the getloot function, 128 00:06:22,339 --> 00:06:24,301 passing on a piece of loot and leave details 129 00:06:24,301 --> 00:06:27,417 of how to store it to the player class. 130 00:06:27,417 --> 00:06:30,421 So our inventory is now encapsulated and isn't 131 00:06:30,421 --> 00:06:34,398 available to any code outside of the player class. 132 00:06:34,398 --> 00:06:37,598 Now another reason for encapsulating data like this, 133 00:06:37,598 --> 00:06:39,680 is let's say we want to store the inventory 134 00:06:39,680 --> 00:06:41,778 to disc whenever it changes. 135 00:06:41,778 --> 00:06:44,035 That way we when I come to play the game again, 136 00:06:44,035 --> 00:06:46,336 my inventory can be loaded back up, 137 00:06:46,336 --> 00:06:48,050 and I'll still have all my loot. 138 00:06:48,050 --> 00:06:50,721 Now before we encapsulated the inventory, 139 00:06:50,721 --> 00:06:52,238 we'll have to add code to store it 140 00:06:52,238 --> 00:06:54,630 each time we added new loot. 141 00:06:54,630 --> 00:06:56,758 Now that's something we could forget to do, 142 00:06:56,758 --> 00:06:58,901 which wouldn't make our players very happy. 143 00:06:58,901 --> 00:07:01,920 So we could introduce a bug into our code quite easily. 144 00:07:01,920 --> 00:07:04,199 But now though, we just need to add the code 145 00:07:04,199 --> 00:07:07,452 to save the inventory in the getloot function. 146 00:07:07,452 --> 00:07:12,452 In other words, to go back now to the player class and here, 147 00:07:14,687 --> 00:07:16,854 code to save the inventory 148 00:07:18,587 --> 00:07:19,976 goes here. 149 00:07:19,976 --> 00:07:22,308 I'm not going to add the code to store the inventory 150 00:07:22,308 --> 00:07:23,901 but you can see how we only have to put 151 00:07:23,901 --> 00:07:26,466 this code in a single place now. 152 00:07:26,466 --> 00:07:28,693 Whenever a new piece of loot gets added, 153 00:07:28,693 --> 00:07:31,296 the inventory could be saved to disc, 154 00:07:31,296 --> 00:07:32,639 and it will always be up to date, 155 00:07:32,639 --> 00:07:36,692 and there's no chance of us forgetting to save it in main. 156 00:07:36,692 --> 00:07:37,696 So that's another reason why 157 00:07:37,696 --> 00:07:40,835 our previous approach wasn't a good idea. 158 00:07:40,835 --> 00:07:42,918 Okay so if we're going to prevent external code 159 00:07:42,918 --> 00:07:44,585 from accessing the inventory, we should 160 00:07:44,585 --> 00:07:47,929 also provide a way to remove items from our loot. 161 00:07:47,929 --> 00:07:50,298 So let's go ahead and write another function here. 162 00:07:50,298 --> 00:07:52,909 We're going to call this one droploot. 163 00:07:52,909 --> 00:07:55,166 It's slightly more complex than getloot, 164 00:07:55,166 --> 00:07:57,775 because we need to make sure that we've got the item, 165 00:07:57,775 --> 00:07:58,998 before trying to drop it. 166 00:07:58,998 --> 00:08:01,217 So let's start with the definition, 167 00:08:01,217 --> 00:08:02,217 fun droploot 168 00:08:04,743 --> 00:08:07,076 (item: Loot 169 00:08:09,086 --> 00:08:09,919 : Boolean. 170 00:08:11,269 --> 00:08:13,704 Then we have that code block. 171 00:08:13,704 --> 00:08:16,371 Then we're going to do return if 172 00:08:17,401 --> 00:08:19,125 inventory dot 173 00:08:19,125 --> 00:08:19,958 contains 174 00:08:20,981 --> 00:08:21,814 item. 175 00:08:23,705 --> 00:08:26,901 Close our parentheses and add another code block. 176 00:08:26,901 --> 00:08:27,984 Inventory dot 177 00:08:29,152 --> 00:08:29,985 remove 178 00:08:31,356 --> 00:08:32,188 item. 179 00:08:34,849 --> 00:08:36,313 True. 180 00:08:36,313 --> 00:08:37,980 The next line, else, 181 00:08:39,331 --> 00:08:40,164 false. 182 00:08:43,578 --> 00:08:45,798 So I've used if as an expression there, 183 00:08:45,798 --> 00:08:48,696 which we covered earlier in this tutorial section. 184 00:08:48,696 --> 00:08:51,798 Now if the item of loot exists in the inventory, 185 00:08:51,798 --> 00:08:54,386 we remove it and return true. 186 00:08:54,386 --> 00:08:57,284 Now if it didn't exist it will return false. 187 00:08:57,284 --> 00:08:58,831 So that's letting the calling code know 188 00:08:58,831 --> 00:09:02,144 that if the item was successfully removed or not. 189 00:09:02,144 --> 00:09:04,438 So let's see how that works in main, 190 00:09:04,438 --> 00:09:06,022 we'll go back to main now. 191 00:09:06,022 --> 00:09:07,395 And right down to the end here 192 00:09:07,395 --> 00:09:10,564 after the last showInventory, 193 00:09:10,564 --> 00:09:12,458 let's try and drop the red potion. 194 00:09:12,458 --> 00:09:14,549 So we're going to put if 195 00:09:14,549 --> 00:09:16,812 (tim 196 00:09:16,812 --> 00:09:17,645 .droploot 197 00:09:18,713 --> 00:09:21,213 that's going to be red potion, 198 00:09:22,373 --> 00:09:23,498 Code block. 199 00:09:23,498 --> 00:09:25,158 Tim 200 00:09:25,158 --> 00:09:26,408 .showInventory. 201 00:09:27,512 --> 00:09:29,587 So let's run the programme and we should find 202 00:09:29,587 --> 00:09:33,754 that the red potion is removed from the inventory. 203 00:09:40,295 --> 00:09:42,330 So you can see we've got our first printout 204 00:09:42,330 --> 00:09:44,225 of Tim's inventory, the red potion was there. 205 00:09:44,225 --> 00:09:47,395 Then after the call to the droploot, 206 00:09:47,395 --> 00:09:50,255 the second time, the second block of code here, 207 00:09:50,255 --> 00:09:51,553 the second block of output, 208 00:09:51,553 --> 00:09:54,489 the red potion is no longer there. 209 00:09:54,489 --> 00:09:56,790 Now we should also test what happens 210 00:09:56,790 --> 00:09:58,617 if an item can't be removed. 211 00:09:58,617 --> 00:10:00,035 So I'm going to create a new piece of loot 212 00:10:00,035 --> 00:10:02,518 and try to remove it from Tim's inventory. 213 00:10:02,518 --> 00:10:04,020 Let's go ahead and do that. 214 00:10:04,020 --> 00:10:08,187 And let's also change this to put an else in here. 215 00:10:09,574 --> 00:10:11,197 Else, code block. 216 00:10:11,197 --> 00:10:12,773 And it'll be 217 00:10:12,773 --> 00:10:13,606 println, 218 00:10:17,209 --> 00:10:18,542 you don't have a 219 00:10:20,432 --> 00:10:23,695 $, that's a right curving braces 220 00:10:23,695 --> 00:10:24,862 redpotion.name 221 00:10:26,218 --> 00:10:28,180 So we're printing something out that's not there, 222 00:10:28,180 --> 00:10:31,017 but let's go ahead and create this other item as I mentioned 223 00:10:31,017 --> 00:10:32,267 val blue potion 224 00:10:35,794 --> 00:10:37,551 is equal to loot 225 00:10:37,551 --> 00:10:40,134 ("blue potion" 226 00:10:42,601 --> 00:10:43,934 loot type.potion 227 00:10:46,489 --> 00:10:49,832 and let's we'll set the value six 228 00:10:49,832 --> 00:10:51,107 Then we'll try doing a drop, 229 00:10:51,107 --> 00:10:52,942 even though we haven't gotten it in the inventory. 230 00:10:52,942 --> 00:10:54,442 So if tim.droploot 231 00:10:57,527 --> 00:10:58,360 bluepotion 232 00:11:00,047 --> 00:11:01,464 tim.showInventory 233 00:11:02,440 --> 00:11:03,273 Else 234 00:11:05,141 --> 00:11:05,974 Code block again 235 00:11:05,974 --> 00:11:08,141 That's going to be println 236 00:11:09,197 --> 00:11:10,364 You don't have 237 00:11:13,670 --> 00:11:14,682 Pound sign 238 00:11:14,682 --> 00:11:18,432 That's right curving braces, bluepotion.name. 239 00:11:23,403 --> 00:11:26,236 Alright so let's try running that. 240 00:11:32,768 --> 00:11:34,523 What I should probably do to avoid some confusion 241 00:11:34,523 --> 00:11:36,300 is just delete that last line there. 242 00:11:36,300 --> 00:11:39,217 So let's just try running it again. 243 00:11:44,639 --> 00:11:46,299 And you can see this time we got the message, 244 00:11:46,299 --> 00:11:48,404 you don't have blue potion. 245 00:11:48,404 --> 00:11:49,657 So that's working well. 246 00:11:49,657 --> 00:11:52,510 Our players can now pick up loot and drop it again. 247 00:11:52,510 --> 00:11:53,343 But what about something 248 00:11:53,343 --> 00:11:55,438 like the Invisibility Potion though? 249 00:11:55,438 --> 00:11:57,309 You can see that the way we've defined it, 250 00:11:57,309 --> 00:11:59,664 we haven't actually got a reference to it in main. 251 00:11:59,664 --> 00:12:02,878 So we can't call the droploot function to drop it. 252 00:12:02,878 --> 00:12:04,591 So that's probably something we probably shouldn't 253 00:12:04,591 --> 00:12:06,644 have called getloot the way we did 254 00:12:06,644 --> 00:12:09,097 for the Ring of Protection and Invisibility Potion 255 00:12:09,097 --> 00:12:11,097 on lines 41 and 42 here. 256 00:12:12,372 --> 00:12:14,070 So this is what I meant earlier, 257 00:12:14,070 --> 00:12:17,670 when I said we need to consider who should own the objects. 258 00:12:17,670 --> 00:12:20,733 Now both those objects really belong to the game. 259 00:12:20,733 --> 00:12:23,126 We should really have created variables to hold 260 00:12:23,126 --> 00:12:26,016 a reference to them in main, so that's how 261 00:12:26,016 --> 00:12:27,933 we've got a way to drop them. 262 00:12:27,933 --> 00:12:30,053 The way we've got our code currently, 263 00:12:30,053 --> 00:12:32,253 there's no way to reference, 264 00:12:32,253 --> 00:12:34,407 there's no reference to either of those bits of loot, 265 00:12:34,407 --> 00:12:37,207 so we've got no way to get Tim to drop them. 266 00:12:37,207 --> 00:12:38,754 Now that's the sort of thing you need 267 00:12:38,754 --> 00:12:40,957 to be aware of when designing your programmes. 268 00:12:40,957 --> 00:12:42,678 After coding for a while, you'll make 269 00:12:42,678 --> 00:12:45,712 the correct decision the first time, most of the time. 270 00:12:45,712 --> 00:12:48,187 Now you still make mistakes occasionally, of course. 271 00:12:48,187 --> 00:12:50,602 Just like I did there, with those two items. 272 00:12:50,602 --> 00:12:53,349 That's fine, that's all part of the learning process. 273 00:12:53,349 --> 00:12:55,847 But of course, in a real game, we'd probably 274 00:12:55,847 --> 00:12:59,099 give the players a way to go through their inventory 275 00:12:59,099 --> 00:13:01,748 and choose items to drop, so in that case 276 00:13:01,748 --> 00:13:03,340 we wouldn't have this problem. 277 00:13:03,340 --> 00:13:06,412 So in our code main is in charge of controlling everything. 278 00:13:06,412 --> 00:13:09,747 The way to fix this then is to change main, 279 00:13:09,747 --> 00:13:12,540 so that we've got references to the Ring and the Potion. 280 00:13:12,540 --> 00:13:13,822 But I'm not going to do that 281 00:13:13,822 --> 00:13:15,203 because this gives us a good excuse 282 00:13:15,203 --> 00:13:16,909 to look overloading a function 283 00:13:16,909 --> 00:13:19,278 and we'll do that in the next video.