字幕列表 影片播放 列印英文字幕 - I am here in this video to talk to you about something called inheritance. Inheritance in the context of object oriented programming and JavaScript and ES6 classes. Oof! So, first of all, there are three core foundational principles to object oriented programming. Let me write those down! There's this idea of encapsulation, there is this idea of inheritance, that is the topic of this particular video, and there is also the concept of polymorphism which I will come back to. And I have made videos on all of these topics before. I can link to them. Those videos, however, were all made in the processing programming environment and looking at these three principles in the Java programming language. Now I am talking about exactly the same thing but in JavaScript. And I have already made a whole set of videos about encapsulation and object orineted programming in JavaScript making use of something called ES6 classes. So one of the things you have to get used to if you choose to spend you life programming in JavaScript is that it's just always changing and there's 500 different ways to do the same thing and everybody's got their opinion on which way is best. And a lot of my older videos used a prototype a prototypical object based way of doing object oriented programming with a constructor function and you'll find those in older coding challenges and you'll even find a set of videos about how to do object oriented programming that way and even one about how to do inheritance that way. And if you watch that you're a true champion because this is wildly confusing and I have no idea if I explain that well. But I am here in this video to talk about ES6 classes. So what is a class? Oh, sorry, ES6 being the version of JavaScript that came out in 2015. It is currently 2019 while I'm recording this. But it is now pretty widely supported across all browsers. So, the idea of a class, and I'm going to use as my example something called particle, because I am demonstrating this in the context of animation and graphics. So I'm drawing particles in a canvas those particles move around the canvas and the class is a template for the making of an object. If I create a particle class, then I can have a variable somewhere else, maybe I call it p, and I can say new particle. An analogy that's often used to describe the distinction between the class and the object is the cookie cutter versus the cookie. So the cookie cutter isn't actually a cookie. It's a thing that you can make cookies with. So this is a template, there's no particle object here. This is just a template to make actual particle objects. And if I have my template I can make more than one particle object each with its own set of properites all made from the same template. So the new key word here, saying new particle means execute something inside the class called a constructor function. So I'm kind of I guess by accident reviewing some of the basics of ES6 classes and object oriented programming to get myself into the inheritance topic. But I'm going to kind of move along because you can find and see many more details and examples about this in the other videos. So this is the basic idea. So let's go over to the code for a second. So what I have over here is a canvas with a little dot moving around. And this dot is an example of a particle object. So here's my class. I have the constructor, the object gets an x and a y and the update function changes the x and y randomly and the show function draws it as a boint. A boint? (laughs) It would be great if there was a function called boint, by the way. Anyway. So let's say now, let's say this is your life, this is what's happening to you. You know what I would like? I would like to put another one of these particles I wanted to, but I want it to look different. And so I want it to be a square particle. So the first thing you might do is like, okay, I'm going to make a Boolean variable like isSquare and I'm going to set that to a square, I'm going to add another argument here square. And then I'm going to say alright, if this dot is square, then draw this as a, not a square a function, then just use rectangle, this dot x this dot y, when will this ever end? At least I could use the square function, it's the least I could do. Could say square, otherwise make it a point, and then, ugh, I'm so tired already. I need a parenthesis here and then I have to go over here, and I could change this to like true because I want it to be a square, and then I refresh and look, it's a square, and then I could say false and it's not. So now I could have two particles, oh, I could have p1 and p2 and I could have p1 do this and p2 do this, oh, I'm so tired. This is so much work and so much coding. And I'm going to call update and show on both of those. And there we go. Now I have my circle and my square. Alright, so that's one solution to this. I have two different mostly the same things with some sort of core essential difference. I don't like this solution. Let me do it another way. I'm going to make another, I'm going to just create a new JavaScript file. I'm going to call it square.js. I'm going to go here, I'm going to copy paste the whole thing paste that in here, I'm going to get rid of this idea of isSquare, and I'm going to have a class called SquareP for square particle. I'm going to get rid of this variable. And then I'm going to, this one's the square so I'm going to draw it as a square. And then this one is the circle so I'm going to draw this just as a plain old point. And I don't need this anymore, and I don't need this. So I have basically a particle class and I have a square class, SquareP class, they're entirely the same but one draws as a square and one draws as a particle. Now I'm going to go back to Sketch.js and I'm going to say new SquareP and I'm going to refresh, and if I did everything right, no, SquareP is not defined because I forgot to reference it in my index.html so let me do that. Then I'm going to go back and there we go! (bell dings) Good night! This video is now over, but not at all! In fact, I'm only just getting started. All of this was exposition. Exposition to the point where we are right now, where we think to ourselves, there has got to be a better way. There has got to be a better way than having some kind of type variable inside of my class and then I use if statements, or to have two separate classes which I've just copy pasted the code and changed some things. How could I have this idea of classes that inherit a bunch of properties from another class, but modify them. And this is in fact what inheritance is for. So let's now think about that in the context of this. What if I could write another class and I'm going to call that class SquareP, which is like the silliest name for a class ever, but it's somehow my example for this video. This is what happens when you record a tutorial after three hours of recording tutorials. Class SquareP, ugh! But I missed the most important piece of this. You had to wait through so much video just to get to this point where now I am going to say extends, and this is the most important thing, particle. This is the keyword. Extends is a keyword in JavaScript. In ES6 that makes the square particle class, the SquareP class, inherit from particle. So let's think about what this is. Now the constructor is a special case. The constructor is a special case where we're going to have to work with it in a different way. But, if what this means is if there is an update function, update function, and if there is a show function, that it's as if I copy pasted the update and the show function into SquareP but I don't actually have to. These functions are now part of the SquareP class. It extends from particle, it inherits particle. This is also sometimes referred to as the child class, or maybe the subclass. And this is often referred to as the super class or the parent class. And the word super is quite important here because that's actually a keyword in JavaScript that's going to allow us to do some interesting things later. In a moment. Now while I could be done by just inheriting update and show and sort of assuming I'm also going to inherit the constructor, it's a good habit, and I think in almost all cases you really need to explicitly write your own constructor even if you are extending another class, but in the case where all I want to do is when I make a SquareP, a square particle, and actually in my Nature of Code book, which this example is mostly the same, I call this class confetti. That's another name I could be using. If I want to just say, you know what? I'm going to define my own constructor but I want to do exactly the same thing as whatever happens in here and the way to do that is just by calling the super function. So the keyword super means execute something from the parent or super class. So super with parenthesis means run the constructor. So let's now actually try to go over and do this in the code. So now what we can do is we can say SquareP extends particle, this is the magic. Once I've extended particle, I can just get rid of this. That stuff is all inherited now from particle! Woohoo! And then I can just say hey, super, do the same thing. And I still have to path in those arguments. This is basically saying hey, you're making a new SquareP. When you make a new SquareP go ahead and make a, call the particle code, the code that's in the particle constructor. So this is now the square particle, let's call this confetti. Just as a different name. Now if I go back to the sketch. And this was left over from before, I forgot that I had this in there. Right, if I run this again, we have two identical particles. It's as if I made two particles because the confetti class, the confetti object is a complete duplicate. It just inherits the particle class completely. But the whole point of this is we can now do things like augment and override. So what if I want my confetti object to always have a color? So maybe I can add another value here. Like I'm going to call this this.bright equals a random number between 0 and 255. So confetti objects do everything a particle does but get an additional property. And then maybe, you know, I want to draw them a different way. I want their physics to be exactly the same so I want to inherit the update function, but I want to draw them a different way. So I can actually override the show function. So if I write a function that has the same name of the function that it's inheriting then this will then be ignored for any confetti objects. And just to change that name here. Let me call this confetti. So let's do that. Let's augment and override. I mean, those are sort of terms, I don't know what the technical terms for those things are. So back over here I might say something like alright, so initialize x and y the same way but add a new property that's a random number between 0 and 255. Then override the show function. You know I could go back and be like, how did I do this? But I don't need to. I don't even need to. I'm just going to say in the show function I'm going to say fill this.bright stroke 255, strokeWeight 1, and then I'm going to say square this.x this.y, and oh, maybe this should also have a variable called r for the side length. And I'm going to make that 10. And then I'm going to say this.r. So now if I run this we can see, look! There is a square, there's a confetti particle, and a regular particle. This is the idea of inheritance. I can have a base class, or I can have a parent class, I can inherit from it, I can add properties and I can override. But guess what I could also do? Let's say what I want to do is, you know, my confetti object, it should update just like a particle updates, but I also want to do one thing more, I want its size to change. So if I come back to here one thing I could do is in the confetti object I could say update and then I could say well, first do whatever you do in the parent object. Call super.update. So do whatever you would normally do for updating and then do one more thing. This.r plus equal random value. So in addition to, in addition to, sorry, changing the, that's going to be too much. In addition to changing the x and y which presumably is taken care of by what it's inherited, also change r. And now, there we go. You can see that this is now having an additional behavior. The size is changing. Now I don't know that the way that I've set this up is particularly elegant or useful, but what I will say is a common technique, especially you'll see this in some of my videos where I work with physics libraries, is that you might have kind of this base class that includes all of the code and math for the physics of how something moves, and you can imagine that being a particle class, but you have all these different variations of that with slightly different behaviors and different design elements so that base class can kind of be the core physics of your system, but lots of different things can exist in your system and be customized in ways without having to duplicate code over and over again. I should also mention that classes can only inherit from one other class, but it is called a tree, an inheritance tree because, and an example I think I've given before in other videos is an animal kingdom. So you could imagine a scenario where you have this idea of an animal class, and maybe that has some properties that all animals share. I don't know what this would be. Weight? That's all I can think of. But then you might have, from that you might have some mammal, a mammal class, a reptile class, those would have things specific to that. And then maybe the mammal from that is going to inherit, there's going to be a canine class. I don't know if this is right biologically or what, but the point is you can inherit things all the way up the tree. So if animal has a property called weight and mammal has a property like fur color, then canine is going to get fur color and weight, it's going to inherit that. Everything inherits. So you can have, it's not a network, it's a tree. And so this is something that's really quite powerful in designing large software systems and working with other JavaScript libraries that you want to have a very flexible and agile way of augmenting and using features from something else while implementing your own thing. This is kind of the core principle of object oriented programming. Of inheritance. So I need to come back and I need to do one more video to talk about one other thing, which is the term polymorphism. Which for me feels a little less relevant in JavaScript, because polymorphism really comes up when you have a strongly typed language cause how you specify what data types certain things are. JavaScript is very good at just kind of figuring it out in lots of cases. But in this case what I can do is I can make an array that's full of lots of different kinds of objects that inherit from each other and then just blanket apply the same thing, the same functions, the same functionality to all of them. So maybe I'll try to do one more video just to basically take this and put it into an array. Alright? Thanks, I hope you got something from this. There's probably like a lot more that you can do, but this maybe gives you an inkling of how inheritance works and might change the way you think about making a project in JavaScript in the future. Thanks! (upbeat electronic music) (bell dings)
B1 中級 16.17: JavaScript中的繼承--JavaScript/ES6專題 (16.17: Inheritance in JavaScript - Topics of JavaScript/ES6) 11 0 林宜悉 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字