Tan115's picture
Add files using upload-large-folder tool
07c2d26 verified
Raw
History Blame Contribute Delete
25.9 kB
1
00:00:06,000 --> 00:00:06,000
Hello, Jim.
2
00:00:06,000 --> 00:00:12,000
Today we're going to learn with you what annotations are, how to work with them and how to create new
3
00:00:12,000 --> 00:00:12,000
ones.
4
00:00:12,000 --> 00:00:18,000
Before we start this lesson, I must say that it is critically important you watching previous lesson
5
00:00:18,000 --> 00:00:20,000
about Reflection API.
6
00:00:20,000 --> 00:00:26,000
If you skip that one, please make sure you watch it, because in this lesson, we are going to use
7
00:00:26,000 --> 00:00:29,000
Réflexion API to work with annotations.
8
00:00:29,000 --> 00:00:35,000
Basically, there is not so much as a ways for us to take advantage from annotations without knowing
9
00:00:35,000 --> 00:00:36,000
the Reflection API.
10
00:00:37,000 --> 00:00:39,000
In this lesson, we're going to learn everything.
11
00:00:39,000 --> 00:00:45,000
The related to annotations will start from the definition of annotation, make you understand what annotations
12
00:00:45,000 --> 00:00:47,000
are on the standard banner.
13
00:00:47,000 --> 00:00:53,000
We are going to discuss use cases when annotations may be applied and for what purposes.
14
00:00:53,000 --> 00:00:57,000
After that, we will start reviewing of the source code examples.
15
00:00:57,000 --> 00:01:02,000
I will explain you what targets annotation is and what retention annotation is.
16
00:01:02,000 --> 00:01:09,000
We are going to create our own custom annotation and you are going to understand how to create it and
17
00:01:09,000 --> 00:01:09,000
process it.
18
00:01:10,000 --> 00:01:15,000
And at the end of the lesson, I will also explain you how to create repeatable annotations.
19
00:01:15,000 --> 00:01:16,000
Let's stop.
20
00:01:17,000 --> 00:01:20,000
And the first question that we have to answer sounds like this.
21
00:01:21,000 --> 00:01:22,000
What is annotation?
22
00:01:22,000 --> 00:01:27,000
Annotation as a form of metadata provides data about programs.
23
00:01:27,000 --> 00:01:30,000
It is not part of the program itself.
24
00:01:30,000 --> 00:01:35,000
Annotations have no direct effect on the operation of the court.
25
00:01:35,000 --> 00:01:38,000
They annotate the understands this definition.
26
00:01:39,000 --> 00:01:40,000
The know what is metadata.
27
00:01:41,000 --> 00:01:50,000
Metadata is a data that provides information about other data or similar data about data in program,
28
00:01:50,000 --> 00:01:57,000
and we can annotate types, colossus and interfaces, fields, masses, parameters, constructors,
29
00:01:57,000 --> 00:02:01,000
local variables, packages, modules and others.
30
00:02:01,000 --> 00:02:04,000
We can even annotate annotation itself.
31
00:02:05,000 --> 00:02:11,000
Basically, there might be cases when you need to provide more information about your code and use this
32
00:02:11,000 --> 00:02:18,000
information on different stages on the level of the source code during compilation and at this stage
33
00:02:18,000 --> 00:02:18,000
of the runtime.
34
00:02:19,000 --> 00:02:25,000
Late in the lesson we are going to learn this case are some examples I will show you where notation
35
00:02:25,000 --> 00:02:29,000
can be applied and how long it will be retained.
36
00:02:29,000 --> 00:02:36,000
You already understood what metadata is and what annotation is, but probably it is still not clear
37
00:02:36,000 --> 00:02:42,000
for you how this can be helpful and when we need to use annotations in which cases.
38
00:02:42,000 --> 00:02:45,000
The first one is information for the compiler.
39
00:02:46,000 --> 00:02:53,000
Annotations can be used by the compiler to detect errors or suppress warnings, for example, such popular
40
00:02:53,000 --> 00:02:54,000
annotation as override.
41
00:02:55,000 --> 00:03:02,000
I am sure you used it already is on purpose or it just added it instead of you overwrite annotation
42
00:03:02,000 --> 00:03:05,000
discarded by the compiler during the compilation.
43
00:03:05,000 --> 00:03:09,000
And there is a specific purpose of this net information.
44
00:03:09,000 --> 00:03:14,000
As you remember, annotation tells us that this method should override method from parent type.
45
00:03:15,000 --> 00:03:22,000
Thus, there are specific requirements to access modify which that matter signature and the list of
46
00:03:22,000 --> 00:03:23,000
potential exceptions.
47
00:03:23,000 --> 00:03:32,000
There is a logical place in juju that analyzes this matter information basically for all methods marked
48
00:03:32,000 --> 00:03:34,000
with overrides, this logic is applied.
49
00:03:35,000 --> 00:03:37,000
Compile time and deployment time.
50
00:03:37,000 --> 00:03:45,000
Processing software tools can process annotation information to generate code, XML files and so forth.
51
00:03:45,000 --> 00:03:51,000
For example, such book in the library and do as number in case you have never worked with.
52
00:03:51,000 --> 00:03:51,000
No.
53
00:03:52,000 --> 00:03:53,000
I will tell you about it.
54
00:03:53,000 --> 00:03:59,000
It generates getters and setters for you and also helps you with generating other things.
55
00:04:00,000 --> 00:04:05,000
This mechanism also built on top of annotations and reflection API.
56
00:04:05,000 --> 00:04:12,000
Basically, you can annotate type was information about methods if you need to be generated, for example.
57
00:04:12,000 --> 00:04:19,000
And when you compile your application and upload classes into Java, those masses that you want it to
58
00:04:19,000 --> 00:04:21,000
be generated are there on place.
59
00:04:22,000 --> 00:04:23,000
Is that clear?
60
00:04:24,000 --> 00:04:27,000
And that's a use case of using annotations is runtime processing.
61
00:04:28,000 --> 00:04:31,000
Some annotations are available to be excellent at runtime.
62
00:04:32,000 --> 00:04:35,000
You can set configuration to retain annotations.
63
00:04:35,000 --> 00:04:39,000
Zero zero runtime I will show you is this an example?
64
00:04:39,000 --> 00:04:41,000
But let's understand why do we need this?
65
00:04:42,000 --> 00:04:48,000
You may need to keep annotations during the runtime to build some logic around this meta information.
66
00:04:48,000 --> 00:04:50,000
You're in the program execution.
67
00:04:50,000 --> 00:04:53,000
Your homework will be related to this case.
68
00:04:53,000 --> 00:04:58,000
I believe that we have learned enough basics to start review and examples.
69
00:04:58,000 --> 00:05:02,000
Anyway, I will explain examples as we go and the true.
70
00:05:02,000 --> 00:05:08,000
Who believes that understanding of this topic will be easier with source code and the real good examples,
71
00:05:08,000 --> 00:05:14,000
rather than with slides for the sake of the demo and this lesson, I created a separate package and
72
00:05:14,000 --> 00:05:15,000
separate them a file.
73
00:05:16,000 --> 00:05:19,000
You can find them a file in annotations package.
74
00:05:20,000 --> 00:05:21,000
Let's start from basics.
75
00:05:22,000 --> 00:05:24,000
Let's discuss annotation format.
76
00:05:24,000 --> 00:05:29,000
Each annotation is started with at sign, followed by some meaningful name.
77
00:05:30,000 --> 00:05:36,000
Z Sign character indicates as a compiler that what follows is an annotation.
78
00:05:36,000 --> 00:05:41,000
The annotation can include elements which can be named and zem values.
79
00:05:41,000 --> 00:05:48,000
For those elements, elements may contain additional information like in this case, you can see that
80
00:05:48,000 --> 00:05:50,000
are used to suppress warnings.
81
00:05:50,000 --> 00:05:54,000
Annotation and element value has value types.
82
00:05:54,000 --> 00:06:01,000
This is basically for compiler to remove warnings for parameterized, at least in case I would Corman's
83
00:06:01,000 --> 00:06:02,000
this annotation.
84
00:06:02,000 --> 00:06:08,000
There will be warnings you as a compilation that I am using parameter types without parameter Ryzens.
85
00:06:09,000 --> 00:06:17,000
You see this OK and other possible syntax of the similar annotation in case there is only one element
86
00:06:17,000 --> 00:06:19,000
is declared inside the annotation.
87
00:06:20,000 --> 00:06:25,000
You can omit element key and just put value like in this example.
88
00:06:25,000 --> 00:06:32,000
It is also possible to use multiple annotations at once and from Java version eight zero even supports
89
00:06:32,000 --> 00:06:34,000
of repeatable annotations.
90
00:06:34,000 --> 00:06:40,000
As you can see in this example, a little bit later in our lesson, one will comp the creation of our
91
00:06:40,000 --> 00:06:41,000
custom annotations.
92
00:06:41,000 --> 00:06:44,000
I will explain you how to create repeatable annotations.
93
00:06:45,000 --> 00:06:47,000
Let's open the source code of any annotation.
94
00:06:48,000 --> 00:06:51,000
For example, let's look at suppress warnings annotation.
95
00:06:52,000 --> 00:06:55,000
As you can see, there is no end in logic and code here.
96
00:06:56,000 --> 00:07:00,000
There is no any algorithm or data processing or anything else.
97
00:07:01,000 --> 00:07:10,000
Some students ask me then how annotations work, how overwrite annotation works, and all this basically
98
00:07:10,000 --> 00:07:15,000
annotations are nothing more than just an information and what you can do.
99
00:07:15,000 --> 00:07:16,000
Learn this information.
100
00:07:17,000 --> 00:07:21,000
This is up to you, and this logic is programmed in a separate place.
101
00:07:21,000 --> 00:07:24,000
OK, that was annotations basics.
102
00:07:24,000 --> 00:07:29,000
Now, you know, at least on the high level, what annotations are us?
103
00:07:29,000 --> 00:07:33,000
Know known annotations deeper and to learn them better?
104
00:07:34,000 --> 00:07:36,000
Let's create our own annotation.
105
00:07:36,000 --> 00:07:44,000
If you are already familiar with G-Unit will implement our own kind of test annotation if you are not
106
00:07:44,000 --> 00:07:45,000
familiar with your units yet.
107
00:07:45,000 --> 00:07:46,000
Just a few words.
108
00:07:47,000 --> 00:07:49,000
G-Unit is a framework for unit testing.
109
00:07:50,000 --> 00:07:56,000
It provides a lot of different features and the Mournes impossibility to run specific methods separately
110
00:07:57,000 --> 00:07:59,000
to execute separate test cases.
111
00:07:59,000 --> 00:08:06,000
The purpose of that massive is to reproduce the state of the system as a specific moment of time, and
112
00:08:06,000 --> 00:08:08,000
the Cert is expected to be here.
113
00:08:09,000 --> 00:08:15,000
All examples will be stored under this package, so you will easily found them in attachments to this
114
00:08:15,000 --> 00:08:17,000
lesson in case you want to run examples on your computer.
115
00:08:18,000 --> 00:08:19,000
Let's start.
116
00:08:19,000 --> 00:08:21,000
I create test annotations.
117
00:08:21,000 --> 00:08:28,000
First, I declare annotation in a separate file, and you can see in this example that the use interface
118
00:08:28,000 --> 00:08:30,000
here was at sign.
119
00:08:31,000 --> 00:08:38,000
The second important step is to add matter annotations to specify the scope and the target of our custom
120
00:08:38,000 --> 00:08:38,000
annotation.
121
00:08:39,000 --> 00:08:43,000
I'm talking about annotations, zero retention and target.
122
00:08:44,000 --> 00:08:44,000
Let's run.
123
00:08:44,000 --> 00:08:45,000
What are they?
124
00:08:46,000 --> 00:08:48,000
So what do we need to target annotation for?
125
00:08:49,000 --> 00:08:54,000
This annotation indicates a context in which an annotation type is applicable.
126
00:08:55,000 --> 00:09:02,000
In simple words, where you can use the sanitation target, annotation can take array of any values
127
00:09:02,000 --> 00:09:04,000
of element type enum.
128
00:09:05,000 --> 00:09:08,000
So even in case you forgot where you can use annotations.
129
00:09:09,000 --> 00:09:16,000
Just open element type in them and you would find enum for each possible placement of your annotation.
130
00:09:16,000 --> 00:09:24,000
Even despite the fact is, a on annotation may take array of elements in our specific example, we would
131
00:09:24,000 --> 00:09:33,000
use only one in a message because in our specific business context, we don't want to allow our client
132
00:09:33,000 --> 00:09:37,000
use it in other places is an exhortation is retention.
133
00:09:38,000 --> 00:09:43,000
This information indicates how long annotations was annotated.
134
00:09:43,000 --> 00:09:45,000
Time are to be retained.
135
00:09:45,000 --> 00:09:49,000
That is exactly what we have discussed at the beginning of our lesson.
136
00:09:49,000 --> 00:09:56,000
When I explained that annotation may be used during Zabeel time by the compiler and discarded from the
137
00:09:56,000 --> 00:10:02,000
class on the glass level but discarded during the anthem, one class is uploaded in.
138
00:10:03,000 --> 00:10:11,000
And during runtime, this annotation can take any value of retention policy in them, even in case you
139
00:10:11,000 --> 00:10:17,000
forgot what's retention levels for annotations are, you always can open the source code of this in
140
00:10:17,000 --> 00:10:19,000
them and explore this.
141
00:10:19,000 --> 00:10:22,000
As I said, there's three possible options here.
142
00:10:22,000 --> 00:10:31,000
They are source Closs, and one time in our case, we use runtime retention policy because we need this
143
00:10:31,000 --> 00:10:33,000
annotation to be retained.
144
00:10:33,000 --> 00:10:34,000
That's a runtime.
145
00:10:34,000 --> 00:10:41,000
Now, at this time, to add custom elements, imagine that you want to specify expected exception in
146
00:10:41,000 --> 00:10:47,000
order we can test negative scenarios, for example, in case we expect exception to be thrown.
147
00:10:47,000 --> 00:10:49,000
But there was no any exception.
148
00:10:49,000 --> 00:10:58,000
Drone zones This particular test should be considered as field and the stanzas declare an element in
149
00:10:58,000 --> 00:10:58,000
annotation.
150
00:10:58,000 --> 00:11:02,000
We have to declare mass was the name of the element itself.
151
00:11:03,000 --> 00:11:06,000
Return type will be the type of the element.
152
00:11:06,000 --> 00:11:12,000
For example, in this specific case, we would like to specify loss of the expected exception.
153
00:11:12,000 --> 00:11:18,000
Thus, returns type for this message will be close when we declare this matter.
154
00:11:18,000 --> 00:11:24,000
We should remember important things, since this massive can throw an exception.
155
00:11:24,000 --> 00:11:27,000
There is a restriction on the return types.
156
00:11:28,000 --> 00:11:35,000
Basically, you can return on your primitives string class in them, annotations and arrays of these
157
00:11:35,000 --> 00:11:36,000
types.
158
00:11:36,000 --> 00:11:39,000
Also, this must has default value.
159
00:11:40,000 --> 00:11:46,000
For example, in this particular case, default exception, to be certain is of non plus.
160
00:11:46,000 --> 00:11:51,000
This is our custom clause that extends Roble and that basically is empty.
161
00:11:52,000 --> 00:11:56,000
This is needed because I can't have default no values.
162
00:11:56,000 --> 00:12:03,000
But in case I wouldn't specify, a default value client will be forced to parse the value for this element.
163
00:12:03,000 --> 00:12:07,000
But what clients should Boston in case there is no expected exception?
164
00:12:07,000 --> 00:12:10,000
That's why I have default non clause here.
165
00:12:11,000 --> 00:12:14,000
Similar example of default value in our other element.
166
00:12:15,000 --> 00:12:19,000
Each test can be named and default name is empty string.
167
00:12:19,000 --> 00:12:23,000
But the client of this code can pass any custom name.
168
00:12:23,000 --> 00:12:26,000
One of the restriction was regards the default value.
169
00:12:26,000 --> 00:12:27,000
It can't be null.
170
00:12:28,000 --> 00:12:29,000
Is that clear?
171
00:12:29,000 --> 00:12:32,000
We are done with annotation creation.
172
00:12:32,000 --> 00:12:34,000
Let's now understand how to use it.
173
00:12:35,000 --> 00:12:39,000
As you can notice, there is no logic defined in the annotation.
174
00:12:39,000 --> 00:12:46,000
That means that I should have some place where logic for annotation process is described in this particular
175
00:12:46,000 --> 00:12:47,000
example.
176
00:12:47,000 --> 00:12:53,000
It can be some tests around the class similar to the G unit, where we have separate runners that can
177
00:12:53,000 --> 00:12:55,000
execute my tests.
178
00:12:56,000 --> 00:12:58,000
I open tests around the class.
179
00:12:58,000 --> 00:13:01,000
It has run tests massive that takes class.
180
00:13:01,000 --> 00:13:05,000
It contains tests to run as mass argument.
181
00:13:05,000 --> 00:13:11,000
I use this reference to a class object to get the array of all masses.
182
00:13:11,000 --> 00:13:18,000
After that, I feel the masses to keep in-stream only masses that have test annotation.
183
00:13:18,000 --> 00:13:24,000
After that, I filter all static masses to keep only non static masses in the stream.
184
00:13:24,000 --> 00:13:28,000
And now I need to call test my asset on the object.
185
00:13:28,000 --> 00:13:31,000
I create new instance using test class.
186
00:13:32,000 --> 00:13:39,000
After that, I need to speak logic for annotations that have expected exception and those who don't.
187
00:13:39,000 --> 00:13:42,000
You remember that annotations results?
188
00:13:42,000 --> 00:13:47,000
Bits of fired by client exception still has exception was not by default.
189
00:13:48,000 --> 00:13:55,000
I use this information during implementation of my logic because in case I expect any exceptions specified
190
00:13:55,000 --> 00:14:02,000
by client other than default, I need to check that the expected exception has been thrown come back
191
00:14:02,000 --> 00:14:04,000
losses of exceptions thrown.
192
00:14:04,000 --> 00:14:06,000
Here is the logic for that.
193
00:14:07,000 --> 00:14:15,000
By the way, in a reflection API in case exception has been thrown on the invoked received in the invocation
194
00:14:15,000 --> 00:14:20,000
target exception that serves as a wrapper for a regional exception.
195
00:14:21,000 --> 00:14:29,000
That's why I need to get course massive here to get the reference to the exception that caused invocation
196
00:14:29,000 --> 00:14:34,000
target exception in case I don't expect exception to this rule.
197
00:14:34,000 --> 00:14:41,000
Massad just should be executed successfully, and I just invoke mass differently.
198
00:14:41,000 --> 00:14:47,000
This is not the full replica of test annotation from G-Unit, but we have a goal in this lesson not
199
00:14:47,000 --> 00:14:53,000
to run G-Unit, but to understand how to work with annotations and process zap.
200
00:14:54,000 --> 00:14:57,000
Now let me show you class with tests.
201
00:14:57,000 --> 00:15:00,000
I open the glass, such as code test samples.
202
00:15:01,000 --> 00:15:02,000
This class contains.
203
00:15:02,000 --> 00:15:05,000
Is different mascots that are marked with test annotation.
204
00:15:06,000 --> 00:15:09,000
Each test has name for the sake of the current demo.
205
00:15:09,000 --> 00:15:17,000
I have two test cases here mascots that is executed without exception and massive that throws exception
206
00:15:17,000 --> 00:15:18,000
of expected type.
207
00:15:19,000 --> 00:15:20,000
Nothing complex here.
208
00:15:21,000 --> 00:15:27,000
And now let's write a code that will use my test runner to run these test cases.
209
00:15:28,000 --> 00:15:32,000
I open another clause at the so-called test annotation demo.
210
00:15:33,000 --> 00:15:34,000
I read instance of test runner.
211
00:15:35,000 --> 00:15:44,000
I could run test method and the person's glass that contains my test cases that so let's run this program
212
00:15:44,000 --> 00:15:45,000
and console.
213
00:15:45,000 --> 00:15:53,000
You can see that test without exception has been passed because we received exception that we expect
214
00:15:53,000 --> 00:16:01,000
and test without exception also has been passed because it was executed without any exception.
215
00:16:02,000 --> 00:16:06,000
I recommend you to look through the source code that I left in attachments to the lesson.
216
00:16:06,000 --> 00:16:11,000
Run it on your local computer to understand better how it works.
217
00:16:12,000 --> 00:16:16,000
And the last thing for the desert I'd like to share with you is repeatable annotations.
218
00:16:17,000 --> 00:16:23,000
To be honest, in my opinion, this is a very rare case because in case you need to pass multiple values,
219
00:16:24,000 --> 00:16:30,000
you always can define additional elements in the original annotation or declare array of values for
220
00:16:30,000 --> 00:16:31,000
some element.
221
00:16:32,000 --> 00:16:39,000
Anyway, it was hard for me to come up with real life example in this case, but I just want to demonstrate
222
00:16:39,000 --> 00:16:42,000
use a feature that was added in Java version eight.
223
00:16:42,000 --> 00:16:44,000
Let me open our demo example.
224
00:16:45,000 --> 00:16:48,000
Can they see that I have Orser annotation here duplicated?
225
00:16:49,000 --> 00:16:56,000
Normally it is not accepted, and to be able to use the same annotation twice for the same element,
226
00:16:56,000 --> 00:16:59,000
you need to perform additional actions.
227
00:17:00,000 --> 00:17:07,000
The first thing to do is to add annotation, repeatable annotation definition, like I did for Orser
228
00:17:07,000 --> 00:17:08,000
annotation.
229
00:17:08,000 --> 00:17:15,000
The second thing to do is to create container for repeatable annotations for compatibility reasons.
230
00:17:15,000 --> 00:17:19,000
Repeating annotations are stored in a container annotation.
231
00:17:20,000 --> 00:17:25,000
In order for the compiler to do this, two declarations are required in your code.
232
00:17:25,000 --> 00:17:30,000
That's why another annotation that we need to create is here.
233
00:17:30,000 --> 00:17:39,000
I call it Auster's container annotation must have element value that returns array with objects of repeatable
234
00:17:39,000 --> 00:17:42,000
annotation type that we want to repeat.
235
00:17:42,000 --> 00:17:47,000
In this case, value element will contain array of Orser annotations.
236
00:17:47,000 --> 00:17:48,000
Is that clear?
237
00:17:49,000 --> 00:17:52,000
Basically, that's all what I wanted to share with you.
238
00:17:53,000 --> 00:17:55,000
Let's review what we have learned in this lesson.
239
00:17:56,000 --> 00:18:03,000
In this lesson, we have learned what annotation is also explained to you, why we might need an addition
240
00:18:03,000 --> 00:18:05,000
and when we can use it.
241
00:18:05,000 --> 00:18:08,000
Now, you know where annotations may be applied.
242
00:18:09,000 --> 00:18:13,000
You know why we need targeted annotation and you know what element type in them is.
243
00:18:14,000 --> 00:18:19,000
Also, you learned what retention annotation is and what retention policy in them is.
244
00:18:20,000 --> 00:18:21,000
In the lesson.
245
00:18:21,000 --> 00:18:27,000
We created our custom annotation, and at the end of the lesson, I explained to you how to create repeatable
246
00:18:27,000 --> 00:18:28,000
annotations.
247
00:18:29,000 --> 00:18:32,000
Basically, that's a summary of all what we have learned today.
248
00:18:32,000 --> 00:18:37,000
I have a homework for you in order you can practice in creation of annotations.
249
00:18:37,000 --> 00:18:41,000
You also can find a link to the whole in attachment to the lesson.
250
00:18:41,000 --> 00:18:44,000
Let's understand what you need to do in this task.
251
00:18:45,000 --> 00:18:49,000
You need to create to do annotation that will allow us to track the progress of note.
252
00:18:49,000 --> 00:18:50,000
Implement that message.
253
00:18:51,000 --> 00:18:57,000
To do annotation has different elements such as author, priority and stages.
254
00:18:57,000 --> 00:19:05,000
Some of them have default values and also Element doesn't have annotation can be applied only to masses
255
00:19:05,000 --> 00:19:07,000
and should be available under on that.
256
00:19:07,000 --> 00:19:14,000
We'll see to create separate classes at the school to do analyzer in that class, we should have massive
257
00:19:14,000 --> 00:19:22,000
three chance string value that is generated to do report pay attention that in order your homework would
258
00:19:22,000 --> 00:19:23,000
be considered to be done.
259
00:19:24,000 --> 00:19:28,000
You need to follow specific partners for each method analysis.
260
00:19:28,000 --> 00:19:30,000
One is described here.
261
00:19:30,000 --> 00:19:35,000
You should specify method name or search priority on stages.
262
00:19:35,000 --> 00:19:42,000
Is it clear any way you will be able to find my solution also in attachments does assessment, but try
263
00:19:42,000 --> 00:19:49,000
to solve this task without any help and by yourself first and only in case solution is not on this for
264
00:19:49,000 --> 00:19:49,000
you.
265
00:19:49,000 --> 00:19:56,000
Use my solution as a reference and as always, in case you have any questions, feel free to add your
266
00:19:56,000 --> 00:19:58,000
questions in comments on this video.
267
00:19:59,000 --> 00:20:01,000
Thanks a lot you for your attention.
268
00:20:01,000 --> 00:20:04,000
Have a great day and see in the next lesson.