Check out a free preview of the full Rust for TypeScript Developers course
The "Generic Trait Implementation" Lesson is part of the full, Rust for TypeScript Developers course featured in this preview video. Here's what you'd learn in this lesson:
ThePrimeagen creates a generic implementation of Collidable by creating a PointIter trait. This trait generically maps over a vector of points. Points and Contains traits are also made. The Contains trait with one method, contains_point, returns a bool if the point is contained within the geometry.
Transcript from the "Generic Trait Implementation" Lesson
[00:00:00]
>> Are you ready for this? I'm ready, I'm excited. So what we're gonna do is we're gonna create something called a pointIter. It'll be the same as our rectIter. It'll take a vector (f64, f64). Again, sorry, for the performance, I know [SOUND]. Anyways, and then we're also gonna have an index that's gonna be zero.
[00:00:16]
So identical to rectIter. The next thing, so let's just do that first right away. So let's go over to our nice collision file and let's create a pointIter. So, struct pointIter. It's gonna have points, which of course, is gonna be a vector(f64, f64). And we're gonna have an index of you size.
[00:00:41]
Okay, this looks just like our rectangle iterator, right? Identical, in fact, awesome. And I'm gonna write this, pub, awesome. And what I wanna do is, I wanna jump over to my rectangle, and I'm just gonna steal the iterator definition, cuz I don't need to do it twice. Does that make sense?
[00:00:58]
So jump over to your rectangle, find rectIter and find the iterator implementation and just take that. Jump back over to collisions and just, I'm just gonna literally go from rectIter to pointIter, there we go. All right, the next thing we're gonna do is, we need to implement, okay, we've done that.
[00:01:22]
We've done that, fantastic. Let's create a convenient method to take a Vec f64 and convert it into a pointIter. All right, so let's do that little convenient method. Does anyone remember what the convenient method would be to be able to take a vector point to convert it into another type?
[00:01:37]
Does anyone remember what it was called?
>> Into?
>> Into is the method name. Impl From <Vac < (f64, f64)> for a pointIter. Look at that, there we go. So we'll just have one of these, make it convenient, right? So we're actually gonna consume a vector, the vector will become ours and now I can just return pointIter.
[00:02:05]
I'm gonna rename this from value to points. Call this thing points, and then index is 0, nice. So long as you give me a vector of points, we'll create a pointIter. I know you can just create an iterator out of a vector, it's not the point here, okay?
[00:02:22]
I'm trying to walk us through creating something a little bit more complex, even though it's probably a bit duplicative, duplicative? What's the right term there?
>> Sounds good to me.
>> Duplicative? Sounds like I'm smart [LAUGH] but, man, am I not [LAUGH], there we go, we got a nice little convenience method, okay, feeling pretty good about it.
[00:02:47]
Remember, it's just from T for another item, right? So it's just two generics here, right? This is a generic, this is a generic. You can kinda implement it in any cross section you want, as long as you own one of the generics. We own pointIter, so it's okay.
[00:03:04]
So we couldn't do it. I believe we couldn't do this because we don't own any of the things. Since we don't own it, you can't implement a foreign trait on a foreign type. I think there's one rule around it with generics. I forget the exact wording of it all.
[00:03:21]
But there you go. All right, so we've already implemented iterator for pointIter. Now let's create a point trait that has one method, points and it returns a point iterator. Well, all right, let's do that. So trait Points, we are making a pub trait, don't forget to make a pub trait, holy cow.
[00:03:46]
And let's have a function Points which returns a pointIter, okay? We're cooking, aren't we? Do you feel the cooking happen now all of a sudden? All right, let's create one more trait. We're gonna call it Contains. And that trait has one method, contains_point that returns a bool. All right, so let's do another pub trait Contains.
[00:04:15]
And this thing has contains_point which is a bool. All right, there we go, feeling pretty good? I think so, I think so. All right, so what's the next thing? I just wanna make sure that I have, okay, good. All right, so why did we do this? There's a reason why we did this and it's very important.
[00:04:41]
We're gonna do something called a blanket implementation. Aah, it's gonna get cozy in here. Okay, here we go. So, let's think about what's going on in our collidable over here. Our collidable is some T and it returns Boolean if they intersect. So what if we do something a bit clever?
[00:05:04]
Let's go like this. Let's implement generic T. So we're starting off with the generic. I know this can get a little rowdy, okay? Implement collidable for that T. This word is gonna get a little, are you ready? Which we implemented for?
>> [INAUDIBLE]
>> T, let's go with T, did you just say T, did I hear that?
[00:05:30]
Let's go, you got this. So we're gonna implement, so collidable <T> for T. Now you're like, okay, how does this work cuz it's generic? We don't have any details on this generic, how are you doing that? Well, we need to constrain the T, where T is Points and it Contains.
[00:05:58]
So that means, for any T that implements both Points and Contains, we will implement collidable for them. So, I know this kind of wow, we're getting kinda into a wild area right now. I get it, okay? So that means, if we look at ourselves, what type is ourself?
[00:06:17]
It's a reference of T. What type is other? It's a reference of T or a Points and Contains. That means we have two methods available on self and other, which is Points and Contains. So I'm like this, for Point in other.points(). If self.contains_point (point) {return true} else {return false}, all right?
[00:06:51]
Hey, well, wah wah wah wah wah wah wah wah wah wah wah, okay, hold on, hold on, what's going on here? My goodness, you're right, I'm so stupid, I forgot to do this whole self thing, it says it right there. [SOUND] I didn't even define my stuff right, all right, and then, of course, we need contains_point.
[00:07:12]
[SOUND] Feel so dumb now, of course. I didn't have it existing on the instance. I had it existing on the class conundrum. I just didn't even see that thing
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops