 Hey everybody, it's Brian. Welcome to the 13th Flutter tutorial. We're going to continue down our Dart learning curve here. We have to learn the Dart language before we can work with Flutter. And we're going to talk about generics today. And we've actually worked with this before. Whenever we've made like a list, like you can see this little snippet code right here. And it's actually has the arguments in every single program we've made so far. So we can do something like list. You know, so I had the E, so we have to define type. And we'll say things. We'll new list. And then we can add things in there. Now, we could have also said string or bool or whatever we wanted to do. So why do we need generics? What's really the value here? Well, let's say we wanted to make a function and let's just say void add. And void, we want to just take something. Let's just say a string. And we want to just add it. So let's actually come back here. Whoops, not string buffer. Geez, we just want to add it here. So we're going to say return value plus one. But now let's say we want to take the same thing. And we want to do it with integers. So now we've got to rewrite this whole darn thing. And now this isn't a string. This is an int. And you can see how now it's complaining that it's already defined. And so now we've got to turn this into add int. And then turn this one into add string. And then we'd have to know which one to call. And you can see how it gets very confusing very quickly. So yeah, we're not messing with any of that nonsense. What we're going to do is we're going to use generics. And what generics allow you to do is they allow you to actually take the type and turn the type into a variable, if that makes any sense whatsoever. And we're going to actually discuss this. But if you read through their examples, they're actually very helpful and very insightful. I went through that section in probably about 10 minutes. It was super easy to understand. So we're just going to dive right in. And we'll say log. Now we want to put these little arrows here. That means anything in these arrows is going to be a type that we're going to use for generics. And we can use that in our program now. And we're just going to print the value. So what effectively have we done here? We've said, hey, we're making a method called log. We want to use generics. So we're going to have a type. That type will change. That's what I mean by that's a variable type now. So that type will change. And here's our actual variable, which is going to be of whatever type we shove in here. And it's just going to print it out. Print takes an object, so it won't actually freak out on us. So now we can say print, let me say hello, or we can even say print and some number. And they both work. See? Down here we've got hello and then whatever number that is, giant long number. My laptop made some weird noise. That kind of scared me a little bit. It was like, it's kind of like Godzilla. It was weird. Anyway, so that is a very super simple example. We can now put anything we want in there. So let's say we want to actually restrict the type. Let's go back to our addition. I'm going to say add. And let's say t extends. And we want to extend the number class here. Now we're not doing inheritance here. That's the confusing bit. What we're doing is we are saying that anything of the t type has to inherit from the number class. Now when I say the t type, I mean this guy right here. So anything that we put into this has to inherit or extend the number class. So let's go ahead and finish this out. We're going to say return value plus one. So what we can say now is print. I'm going to say add. Just going to say one. And this should print the number two. And there it is, number two. So if we take this and we now try to do something like this, you can see how it's already mad at us saying an argument string cannot be assigned to the parameter type num because it knows it has to extend the number class. And if we try to run it, of course, it just explodes on us and says nope, can't do it. And it even tells you why type int is not some type of string or other where and then it just shows you. So that is one way of limiting that right there. So let's get a little more complex here. Let's actually work with a class. And I know I say complex, but this is actually just dead simple to work with. And I'm almost embarrassed making a tutorial on this because it's so easy to work with other languages generics get very complex very quickly. But Dart makes it very simple. I think they kind of borrow some of the best parts of other languages. But that's just my humble opinion. So we're just going to have a dog class, the dogs want to speak. And then we're going to make a new class. We'll call this stray, which is like a stray dog kind of thing. I'm going to import the dog class. And this stray is really not going to do anything. I mean, we're not going to have any properties in it. And then we're going to make a trainer class here. And we're going to import the dog class, because we're going to be working with that. I'm going to say class trainer. And we want to have our generic type in there. And in here, we want to say, okay, void add. And we want to have our t value. And whoops, I missed a step here. Doesn't make much sense what I'm doing if we don't have this. So what we're going to do is just make an internal list here. And this is not uncommon for a lot of programs. All right, now this will make a little more sense what we're doing. Then we're going to fat arrow this into animals. And we're going to just going to add the value there. So we're going to be able to add or move to that internal list. And then we're just going to say void train. And if you have no idea what I'm doing here, I encourage you to watch my previous tutorials. We're just going to do that. And then we're going to say for int I equals zero. I is less than three, because why not? And then going to increment. So now we're going to say value that speak. This looks weird. Let's talk about this. Okay, so what we're doing here is this is our generic class. The dog is just a normal class, the stray just extends. Whoops, we actually didn't even do that extends the dog class. And then the trainer itself is just a generic class. Now when I say generic, I mean it's using this. And you can see internally we're using this list and we're actually using the same type. And we're just going to add or move values to that list. And then we're going to work with that list. Now you notice how instantly it's saying the method speak isn't defined for class object. What does that mean? Well, it means that we actually have never defined this. We haven't said what it extends. So it's going to automatically extend the object class, which is the base class for pretty much everything in Dart. The base class object does not have a method called speak, which is why it's saying, ta-da, object doesn't have that method. Now, let's try to work with this and just see what happens here. And let's say, oops, I don't want dog, I want stray. Now we're going to make, you guessed it, a trainer. And we're going to say, trying to think of a good name, it's why I'm sitting here for a minute going, let's say, stray, and let's call him, why not? Let's call him Bob. And then let's do this, bob.add. We're going to add Fido into this. So Bob's going to train Fido basically is what's going on here. So we are adding Fido. We're going to train all the dogs in the list. And then we're going to remove Fido because Fido has been trained. And let's see what happens if we run this. And it says, woof, woof, woof. So now back up. Wait a minute, what's going on here? Notice how we've done a couple of things. We haven't added the generic, or we haven't added the type in here. But Dart was smart enough to know that because it's here, we're doing it. Also in the trainer class, it's still saying method speak isn't defined. This is a perfect example of what's called polymorphic programming, which means that your program changes based off the input. If we were to put a integer in here, it's going to die because integer doesn't have a speak in here. And let's actually try that. Let's say, let's say one and one, that's probably not going to work. Let's try it. Yeah, see, boom. Class int has no instance method of speak. So the same code did work, but didn't work. If you kind of follow what I mean, it works for what we programmed it for, but it didn't work for integers. So what we need to do now is go back in and modify this a bit. And you guessed it, we are going to say extends the dog class. Now suddenly it clears up and it knows that, hey, dog and anything that inherits from or extends from dog actually has that. So now this should just work fine. Whoa, whoa, whoa, there we go. So just some little caveats is you should be a little careful with generic programming. It's a bit of an advanced topic. A lot of questions that I get when I talk about generic programming in other languages is why. I mean, when do you actually use this? You'll see a lot of generics in core libraries, things like lists, for example. So if you're making a program that takes plugins, for example, you would have a base plugin that all other plugins would extend or inherit from. And in your generic programming, you would, just like we did with the trainer here, you would extend that base plugin. That would be a really good example. Another thing would be like if you're making like a music player, you would have a music player, you would have a generic class called song or file or whatever, and everything would extend upon that. And then you would have your base methods in there. So another question I always get is how do you have more than one? Like there's T, what if you wanted like a couple? You just simply separate them by commas like that. We have E and H in there. Now we could use E and H, but then you have to, in our file here, you see how they're suddenly exploding, we would have to say int and string. And they would have to match up. Probably help if I spelled string correctly here. Yeah, really, really screwed that one up here. Sorry, guys. And then you would have to, you know, obviously work with the extra types as needed. But I'm going to get rid of those because I don't want them to be part of the example here. Just remember that generics are a bit of an advanced topic. And really, it's a powerful tool. The problem with a powerful tool is that when you hit yourself in the foot with it, it's going to hurt a lot worse. And you'll get some weird errors like this value speak. Like if we didn't extend dog, if we just let it extend object automatically, and we throw the wrong value type or the wrong variable type in there, suddenly the program starts crashing, we're trying to figure out why. So just be mindful of that. As always, thank you for watching. I hope you found this educational and entertaining. There is a void realms Facebook group with 1700 other programmers out there. We can help you with just about anything you need. Very good group of folks. I'm constantly asking questions in there. And the source code for this and all other tutorials is out on GitHub. You can just simply visit void realms.com and the link to the tutorials is right out there. Oh, I should mention, we did have a nasty bug with our group where if you try to join, it said you don't have permissions to modify the group. We have since fixed that. So go ahead and send your your request and we'll get you in the group as fast as we can. That's it. Thank you for watching.