All language subtitles for 9. [Dart] Functions as First Order Objects

af Afrikaans
sq Albanian
am Amharic
ar Arabic Download
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bn Bengali
bs Bosnian
bg Bulgarian
ca Catalan
ceb Cebuano
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
tl Filipino
fi Finnish
fr French Download
fy Frisian
gl Galician
ka Georgian
de German
el Greek
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
km Khmer
ko Korean
ku Kurdish (Kurmanji)
ky Kyrgyz
lo Lao
la Latin
lv Latvian
lt Lithuanian
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mn Mongolian
my Myanmar (Burmese)
ne Nepali
no Norwegian
ps Pashto
fa Persian
pl Polish
pt Portuguese
pa Punjabi
ro Romanian
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
st Sesotho
sn Shona
sd Sindhi
si Sinhala
sk Slovak
sl Slovenian
so Somali
es Spanish
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
te Telugu
th Thai
tr Turkish
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu
or Odia (Oriya)
rw Kinyarwanda
tk Turkmen
tt Tatar
ug Uyghur
Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated: 0 1 00:00:00,570 --> 00:00:05,980 Now in the last lesson, we vastly simplified and refactored our code. 1 2 00:00:06,240 --> 00:00:10,020 And now it looks a lot simpler and a lot easier to read. 2 3 00:00:10,560 --> 00:00:16,200 But there's just one thing. We know that we're currently using a reusableCard to be able to create a 3 4 00:00:16,200 --> 00:00:23,380 card that has a particular margin or a particular look or a particular rounded border. 4 5 00:00:23,400 --> 00:00:31,950 But we're also adding it as a child to a gesture detector to be able to detect when the user taps on 5 6 00:00:32,010 --> 00:00:36,350 that card, and when that happens we set the selectedGender. 6 7 00:00:36,360 --> 00:00:44,040 Now it's really likely that for other reusable cards, we might also want this functionality, being able 7 8 00:00:44,040 --> 00:00:45,530 to detect touch. 8 9 00:00:45,690 --> 00:00:51,840 And even if we don't need to, there's still two areas where we are repeating the same code right? 9 10 00:00:51,930 --> 00:00:54,620 Adding a gesture detector to the reusableCard. 10 11 00:00:55,050 --> 00:01:01,900 So why don't we just bite the bullet and upgrade our reusableCard to also be able to detect touch? 11 12 00:01:02,070 --> 00:01:05,840 And that's what we're going to do in this lesson. And in the process, 12 13 00:01:05,880 --> 00:01:11,070 I'm going to show you something really cool that you can do with Dart which is passing around functions 13 14 00:01:11,310 --> 00:01:14,130 as if they were just any other object. 14 15 00:01:14,130 --> 00:01:19,440 And I've just noticed that I've actually got a typo in the name of my file. 15 16 00:01:19,650 --> 00:01:25,380 Over here you can see that I've written imput instead of input, but this is really easy to fix because 16 17 00:01:25,380 --> 00:01:27,700 it's not affecting any of our code. 17 18 00:01:27,700 --> 00:01:34,380 So if you ever get a typo or a spelling mistake in your file name, simply just right click on it and 18 19 00:01:34,440 --> 00:01:43,420 click on refactor, rename and it will change all the places where this is used. So let's change that input 19 20 00:01:43,500 --> 00:01:44,710 it will search for references, 20 21 00:01:44,730 --> 00:01:52,080 search for comments and strings and it'll refactor everything to the right spelling. In Dart,functions 21 22 00:01:52,160 --> 00:01:53,980 are first class citizens. 22 23 00:01:54,000 --> 00:01:59,250 This means that they have a type and they can be passed around just like any other type 23 24 00:01:59,250 --> 00:02:06,300 for example a string or an int. And they can also be set as the value of a variable or a constant. 24 25 00:02:06,330 --> 00:02:09,360 So let's take a look at this now. 25 26 00:02:09,480 --> 00:02:13,050 So here in my DartPad, I've got two functions. 26 27 00:02:13,050 --> 00:02:18,060 One is a function called add which simply as the two numbers that it's given. 27 28 00:02:18,180 --> 00:02:19,290 And the second one is called 28 29 00:02:19,290 --> 00:02:23,030 multiply and it multiplies the two numbers that it's given. 29 30 00:02:23,040 --> 00:02:30,990 Now if I wanted to perform a calculation, I could say add and then provide my numbers 3 and 5 30 31 00:02:31,050 --> 00:02:35,210 for example, and then I would end up with a result. 31 32 00:02:35,340 --> 00:02:42,960 So let's call it a int result equals the result of the add and then we'll print the result to the console. 32 33 00:02:43,650 --> 00:02:47,050 And you can see that I will be able to run it as it is. 33 34 00:02:47,400 --> 00:02:54,030 But what if I wanted to build a calculator where the user is able to tap on the plus button or the minus 34 35 00:02:54,030 --> 00:02:57,330 button and perform the calculation that they need? 35 36 00:02:57,330 --> 00:03:01,730 Well what if instead of having to call a different function each time instead, 36 37 00:03:01,920 --> 00:03:11,550 what if I create a new function that returns an int and it's called calculator and it not only takes 37 38 00:03:11,640 --> 00:03:19,390 two numbers int n1 and int n2, but it can also take a function as an argument? 38 39 00:03:19,440 --> 00:03:22,380 So we would be able to add it as a type. 39 40 00:03:22,410 --> 00:03:27,300 So for a string it would be string for an int it would be an int. But for function we would just write the 40 41 00:03:27,300 --> 00:03:30,470 name Function with a capital F. And we could give it a name 41 42 00:03:30,480 --> 00:03:33,140 let's call it calculation. 42 43 00:03:33,140 --> 00:03:41,280 And then inside the body of the function, I will perform the calculation on those two numbers n1 and 43 44 00:03:41,370 --> 00:03:49,740 n2. And then I would return the result of this calculation as the output of my calculator. 44 45 00:03:49,740 --> 00:03:56,820 Now what I'm able to do is instead of having to call add then multiply then whatever, then in this case 45 46 00:03:56,910 --> 00:04:04,770 I could simply write the result is going to be calculator performing a function on two numbers, let's 46 47 00:04:04,770 --> 00:04:10,380 call it 5 and 8, and then the third input here is a function. 47 48 00:04:10,380 --> 00:04:14,300 It's expecting an actual function as an input. 48 49 00:04:14,310 --> 00:04:16,620 So I'm simply going to add the name. 49 50 00:04:16,680 --> 00:04:22,950 So for example, add. Well in this case, it's clear that I want my calculator to perform some sort of function 50 51 00:04:23,040 --> 00:04:26,730 on 5 and 8 and then add them together. 51 52 00:04:26,760 --> 00:04:31,690 So now if I hit run you can see that it's going to try and add 5 and 8 together. 52 53 00:04:31,800 --> 00:04:40,170 But if I simply switch out the parameter here into multiply, as long as I spell it right, then it will 53 54 00:04:40,260 --> 00:04:42,900 multiply 5 and 8 together. 54 55 00:04:42,900 --> 00:04:49,440 So functions are being passed around just as any other types, so if it was an int or if it was a string. 55 56 00:04:49,710 --> 00:04:56,630 And this gives us a lot of flexibility and it's really powerful as we'll come to see. Now 56 57 00:04:56,640 --> 00:05:04,260 the other thing that we can do with functions is we can even assign a function as the value of a variable. 57 58 00:05:04,590 --> 00:05:11,490 So for example instead of saying int calculator, I could simply create a new variable that is of type 58 59 00:05:11,490 --> 00:05:19,290 Function and I could call it calculator and I will set it to equal my function here. And at the very 59 60 00:05:19,290 --> 00:05:22,200 end, I just have to cap it off with a semicolon. 60 61 00:05:22,230 --> 00:05:25,200 So now it works exactly the same way as before. 61 62 00:05:25,230 --> 00:05:33,780 If I click run and I change it to add or multiply, doesn't really matter, it still works as is. My function 62 63 00:05:34,260 --> 00:05:40,750 is now stored inside a variable called calculator and I could even make this a final variable if I wished 63 64 00:05:40,760 --> 00:05:41,040 to. 64 65 00:05:41,220 --> 00:05:47,520 Which means that I'm no longer able to change the assignment of my calculator so I can't say calculator 65 66 00:05:47,550 --> 00:05:53,370 now equals a different function for example. It'll give me an error telling me that calculator is a final 66 67 00:05:53,370 --> 00:05:57,750 variable and can only be set once. 67 68 00:05:57,750 --> 00:06:03,870 Now notice how at the moment, I'm creating functions completely outside of any classes and even outside 68 69 00:06:03,930 --> 00:06:05,280 of the main function. 69 70 00:06:05,410 --> 00:06:07,750 And this is perfectly legal in Dart. 70 71 00:06:07,830 --> 00:06:14,150 You can have top level functions just like this and they are not associated with any class or object. 71 72 00:06:14,670 --> 00:06:16,980 But let's see how it works inside a class. 72 73 00:06:16,980 --> 00:06:25,560 So I'm going to delete all the code so far and I'm going to create a new class called Car. And car is 73 74 00:06:25,560 --> 00:06:32,580 going to have a property that is a function and it's going to be called drive. 74 75 00:06:32,580 --> 00:06:37,740 Now this property will be initialized when car gets constructed. 75 76 00:06:37,800 --> 00:06:46,890 So I'm going to create my car constructor and I'm going to write this.drive to say that when I construct 76 77 00:06:46,950 --> 00:06:53,520 my car, I have to provide a drive method to associate it with my car object. 77 78 00:06:54,930 --> 00:07:02,760 Let's say that we have two modes of driving right? Let's create one which is called slowDrive, and in 78 79 00:07:02,760 --> 00:07:06,630 this case it's simply going to print 'driving slowly'. 79 80 00:07:09,240 --> 00:07:14,220 And then let's say we have another one which is called fast drive 80 81 00:07:14,880 --> 00:07:22,500 and in this case it will print 'driving super fast.' 81 82 00:07:22,790 --> 00:07:23,110 All right. 82 83 00:07:23,140 --> 00:07:29,200 So now I have two functions which are top level functions. They are not associated with any class. But when 83 84 00:07:29,200 --> 00:07:38,650 I initialize my car in my main function, for example I could say myCar is equal to a new car which 84 85 00:07:38,650 --> 00:07:40,910 is constructed from the Car class. 85 86 00:07:41,020 --> 00:07:46,130 And I now have to provide a value for the drive property. 86 87 00:07:46,210 --> 00:07:50,120 So the drive property is going to be set equal a function 87 88 00:07:50,140 --> 00:07:50,570 right? 88 89 00:07:50,590 --> 00:07:51,960 So it's expecting a function. 89 90 00:07:51,970 --> 00:07:58,920 I can't just put in a number, say 2 or I can't put in a string because it needs to be of the type function. 90 91 00:07:58,930 --> 00:08:03,820 So let's give it a function because we have to. We can either say slowDrive or fastDrive. 91 92 00:08:03,820 --> 00:08:07,490 Well let's say that my car starts out being a slowDrive car. 92 93 00:08:07,690 --> 00:08:12,670 And notice how I'm not actually adding any parentheses after the function. 93 94 00:08:12,670 --> 00:08:16,330 I'm simply passing over the name of that function. 94 95 00:08:16,360 --> 00:08:23,590 So now at this stage myCar.drive is associated with the slowDrive function. 95 96 00:08:23,590 --> 00:08:28,320 So I could show you this by simply running print myCar.drive. 96 97 00:08:28,510 --> 00:08:34,390 And notice again I'm not putting a set of parentheses after drive because that is the thing that will 97 98 00:08:34,390 --> 00:08:35,850 activate the function. 98 99 00:08:35,860 --> 00:08:39,910 So right now if I print, you'll notice it'll print Closure 'slowDive'. 99 100 00:08:39,910 --> 00:08:43,300 So that's pointing to this particular function. 100 101 00:08:43,390 --> 00:08:49,770 It's saying that in myCar the drive property is equal to slowDrive. 101 102 00:08:49,900 --> 00:08:55,450 But if I actually wanted to call my drive method, I would say myCar.drive. 102 103 00:08:55,600 --> 00:08:59,500 And I would add the parentheses and any inputs if necessary. 103 104 00:08:59,500 --> 00:09:05,520 And it's this line that actually triggers the drive method that is associated with my car. 104 105 00:09:05,950 --> 00:09:09,270 And we're getting driving slowly printed to the console. 105 106 00:09:09,340 --> 00:09:12,250 Now let's say that I wanted to upgrade my car right? 106 107 00:09:12,280 --> 00:09:13,470 I will say myCar 107 108 00:09:13,490 --> 00:09:19,270 .drive, the drive property is now going to be equal to fastDrive. 108 109 00:09:19,270 --> 00:09:21,880 And again no parentheses after the method. 109 110 00:09:21,880 --> 00:09:27,340 But I'm simply changing the value of that drive property on myCar. 110 111 00:09:27,340 --> 00:09:29,190 So now I've taken my car to the garage. 111 112 00:09:29,200 --> 00:09:34,450 It's being souped up. Now it's going to turbo and it's supercharged and it's blazing. 112 113 00:09:34,450 --> 00:09:40,750 So now when I write myCar.drive and we print out the result. 113 114 00:09:40,810 --> 00:09:43,180 So I'm going to comment out that line. 114 115 00:09:43,180 --> 00:09:52,390 And now you can see that myCar's been upgraded and now it's driving super fast. When I'm passing functions 115 116 00:09:52,390 --> 00:09:55,280 around, I'm just using its name. 116 117 00:09:55,390 --> 00:09:57,200 I'm not adding the parentheses. 117 118 00:09:57,250 --> 00:10:03,610 And when I want to call the method and actually trigger the functionality that's when I add the parentheses 118 119 00:10:03,760 --> 00:10:12,570 and any inputs if necessary. Now that we've seen how flexible functions can be and how they can be passed 119 120 00:10:12,570 --> 00:10:16,430 around just like any other object or any other type, 120 121 00:10:16,590 --> 00:10:21,570 it's time for your challenge to apply what you've learned to our code. 121 122 00:10:21,570 --> 00:10:29,340 The goal of the challenge is to do the gesturedetector on the first icon card and also the second 122 123 00:10:29,340 --> 00:10:33,390 one and refactor it into the reusableCard 123 124 00:10:33,390 --> 00:10:41,400 .dart file. So that way we can actually pass a function into our reusableCard just as we've passed 124 125 00:10:41,460 --> 00:10:50,130 a color property or a cardChild and our function is also going to be passed as a value for one of these 125 126 00:10:50,340 --> 00:10:51,390 properties. 126 127 00:10:51,420 --> 00:10:56,370 So if you're successful by the end nothing about your app will have changed other than the fact that 127 128 00:10:56,370 --> 00:11:02,220 the gesture detector should now live in the reusableCard and inside this build method. 128 129 00:11:02,700 --> 00:11:08,540 Pause the video and see if you can solve this challenge. All right. 129 130 00:11:08,560 --> 00:11:14,290 So first things first. I'm going to simply delete my gesture detector from this page. So I'm going to 130 131 00:11:14,290 --> 00:11:20,980 hold down OPTION or ALT, hit ENTERand I'm going to remove my widget from both places. 131 132 00:11:21,400 --> 00:11:25,910 So both in the first card and the second card. 132 133 00:11:26,170 --> 00:11:32,560 Now I just have a pure reusableCard and I'm going to pass over the functionality where I set state 133 134 00:11:32,620 --> 00:11:39,630 and change the selectedGender when the user clicks on this card or this card into my reusableCard. 134 135 00:11:39,640 --> 00:11:45,700 So inside here in the build method, instead of just returning a container, I'm actually going to wrap 135 136 00:11:45,700 --> 00:11:48,850 the container inside a gesture detector. 136 137 00:11:50,870 --> 00:11:59,360 And here of course I will now again have access to the onTap. And I'm going to pass over a function 137 138 00:11:59,540 --> 00:12:02,810 into my reusableCard widget. 138 139 00:12:02,840 --> 00:12:09,350 So in exactly the same way that we did with our previous two properties, color and cardChild, I'm going 139 140 00:12:09,350 --> 00:12:14,640 to add another final property which is going to have a function as the type. 140 141 00:12:14,780 --> 00:12:22,520 And I'm going to call it onPress. And this is also going to be initialized when I create a new reusable 141 142 00:12:22,520 --> 00:12:22,850 Card. 142 143 00:12:22,880 --> 00:12:29,060 So I'm going to add the this.onPress over here so that I can pass over whichever function I want 143 144 00:12:29,060 --> 00:12:32,640 to be used inside my reusableCard. 144 145 00:12:32,810 --> 00:12:37,810 And then it's going to be set as the value of the onTap. 145 146 00:12:37,820 --> 00:12:44,360 So this means that when I create a reusableCard, I can specify a function that is going to be the function 146 147 00:12:44,360 --> 00:12:49,880 that will be called when the gesture detector detects a tap on the reusableCard. 147 148 00:12:50,300 --> 00:12:57,620 So now I can go back to my input page and add some properties to my reusableCard. So I can add my on 148 149 00:12:57,620 --> 00:13:00,320 Press which I just defined just now, 149 150 00:13:00,320 --> 00:13:04,010 and it's going to be the same as what we would have done with the gesture detector. 150 151 00:13:04,010 --> 00:13:09,920 We're going to add an anonymous function and inside the anonymous function, we have our set state and 151 152 00:13:09,920 --> 00:13:10,870 inside the set state, 152 153 00:13:10,880 --> 00:13:19,700 we change the selectedGender to gender.male in the first reusableCard and in our second reusable 153 154 00:13:19,700 --> 00:13:20,360 card, 154 155 00:13:20,480 --> 00:13:31,200 we have our onPress and in this case the set state is going to change the selectedGender to female. Now 155 156 00:13:31,260 --> 00:13:40,150 when I hit save on my code, nothing about my app will change. You can see that it still works exactly 156 157 00:13:40,150 --> 00:13:47,640 the same way as it did before, but now we've simply refactored the ability for our reusableCard, 157 158 00:13:47,650 --> 00:13:54,370 this custom widget that we've built based on gesture detector, based on containers, based on box decorations 158 159 00:13:54,370 --> 00:14:02,240 etc. and it's now also able to take a onPress. So it's able to respond to taps. 159 160 00:14:02,290 --> 00:14:08,440 So we've essentially upgraded our reusableCard to also be able to detect touch simply by passing 160 161 00:14:08,440 --> 00:14:18,470 over a function as the value of the onPress property. And the result of this is cleaner code with less 161 162 00:14:18,470 --> 00:14:26,180 things being embedded and all the functionality and the design is now together in one widget. 162 163 00:14:26,180 --> 00:14:30,690 It's always good practice to refactor your code as you go along. 163 164 00:14:30,890 --> 00:14:36,720 This way you don't end up with spaghetti code at the end and lose all motivation to tidy it up. 164 165 00:14:36,740 --> 00:14:42,590 You know that when your room gets to a certain state where it's just no longer possible to recover it 165 166 00:14:42,650 --> 00:14:43,670 and then you give up. 166 167 00:14:43,790 --> 00:14:45,160 That's not what we want with our code. 167 168 00:14:45,170 --> 00:14:48,140 We want it to be neat and tidy and performance. 168 169 00:14:48,140 --> 00:14:54,050 Now in the next lesson, we're going to continue working on the other cards that we have in our user interface. 169 170 00:14:54,500 --> 00:15:01,870 And we're going to implement a Flutter slider to be able to select the user's height on a scale. 170 171 00:15:01,880 --> 00:15:04,580 So for all of that and more, I'll see on the next lesson. 19681

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.