Document directory
- I. How to encapsulate it?
- Ii. How to inherit?
- 3. How is polymorphism?
I haven't written a blog for a long time. I suddenly remembered that JS oo had an idea and implemented it, so I used it as the content of the new blog.
For JS Oo, here is a list of my previous experiences and experiences in this aspect. If this is not correct, I should raise it.
- JS oo inheritance and Polymorphism
- Horizontal comparison of JavaScript "class" inheritance
- Day 5: javascript inheritance
- Inheritance mode in Yui 3 and Its Usage
- Use the super keyword in Ext. Extend ()
Looking at the number of JS oo implementation methods, there are always some internal shortcomings. I have tried some projects and have never been satisfied. Is there any deficiency or dissatisfaction? -- I have mentioned in my previous blog posts ......
The method described in this article, based on the typical JS class writing method, expands its implementation of the overload method (overload), and still uses the JS prototype inherited mode to process inheritance. Therefore, when two old usages (Classic writing and prototype inheritance) and a new implementation of "overload", "overload" is the highlight of this method, and there is nothing special about it.
I. How to encapsulate it?
First, let's talk about the typical JS writing method. This method adopts the "classic" class writing method, and can only be used. Other writing methods are invalid. The so-called "classic" writing method is the method that the textbook tells you when we first learned JS (Example 1 ):
Function myclass () {<br/> // Private local varialbies <br/> var localvar; <br/> // public variabies <br/> This. publicvar = 0; </P> <p> // Private methods <br/> function privatemethod () {</P> <p >}</P> <p> // public method <br/> This. publicmethod = privatemethod; <br/>}
Instead of modifying the prototype object:
Function myclass () {<br/> // Private local varialbies <br/> var localvar; </P> <p> // Private methods <br/> function privatemethod (a) {</P> <p >}< br/> myclass. prototype = {<br/> // public variabies <br/> publicvar: 0, <br/> // public method <br/> publicmethod: function () {</P> <p >}< br/> };
It seems that fewer and fewer people are using the first classic writing method. Does this mean that the second writing method should be promoted only by highlighting the essence of JS "prototype inheritance? I don't know. In short, you like it. However, in the JS oo inheritance method described in this article, the first method is the classic method. In this way, it is more like a Java class ~ Haha.
Let's talk about "Example 1. In the class myclass, the Comment private local variablies refers to a private internal variable. If it starts with "Var", the outside world cannot be accessed. Otherwise, the variables or methods assigned by this are used, it can be accessed by the outside world. Please note this. publicmehtodd = privatemethod here, both private and public methods point to the same function. Of course, here is a special case. We usually write it by splitting.
Writing code into a class is to better encapsulate and form an API for calling. Here we define the encapsulation method as the classical JS class writing method, followed by inheritance.
Ii. How to inherit?
Javascript has only one inheritance method, which is prototype inheritance. There are two classes: Base base class and son class. Son class is the derived class of base class. This completes an inheritance:
Base = new base; <br/> son. Prototype = base; // prototype inheritance!
Each time a new class is defined, a copy of its parent class's instance is saved. The parent class is unique for child classes. The above process is very simple, but the solution below will be a little more complicated. Add a superobjs array and the array will save all the parent classes. The Code is as follows:
Base = new base; <br/> If (! Base. superobjs) {<br/> base. superobjs = [base]; <br/>} else {<br/> base. superobjs. push (base); <br/>}< br/> son. prototype = base; // prototype inheritance!
What is the purpose of adding an array of superobjs? Here, press "no table" to make a foreshadowing, which will be useful later.
There are still no new ideas here. What are we doing? Well, of course, we will reveal the problem.
There is a big problem in the writing of classic encapsulation and inheritance. Method Overloading is not allowed. Simply put, it is the class that follows, the method with the same name will overwrite the method with the same name as the original class. The time of overwriting occurs in the new subclass.
How can this problem be solved? There is still a solution. See the following source code:
// Access the internal function of the parent class <br/> // written by Frank Cheung <br/> function _ super () {<br/> var <br/> byexplicit = arguments [0] <br/>, byexplicit = byexplicit & byexplicit. length & byexplicit. callee <br/> // If explicit, it means arguments. caller === arguments (old) // true! <Br/> // if not explicit, it means get method by arguments. Caller. callee. <br/>, overrided = byexplicit? Arguments [0]: arguments. Caller. callee <br/>, the membername // member name remains unchanged. The name string used as the creden。 of the query member. <Br/>, supermember // found super member <br/>, superobjs = This. superobjs // parent class list <br/>, superobj // current parent class (not necessarily the target parent class) <br/>, argS = byexplicit? Array. Prototype. Slice. Call (arguments, 1): arguments; </P> <p> If (! Overrided) {<br/> debugger; <br/> error. throwerr ({<br/> MSG: "The args object must be input! "<Br/>, method: arguments. callee <br/>}); <br/>}</P> <p> // locate the member name first. <Br/> for (var I in this) {<br/> If (this [I] = overrided) {<br/> membername = I; <br/>}</P> <p> for (VAR I = 0, j = superobjs. length; I <j; -- j) {<br/> superobj = superobjs [J-1]; <br/> supermember = superobj [membername]; </P> <p> If (supermember) {<br/> return typeof supermember = 'function' <br/>? Supermember. Apply (this, argS) <br/>: supermember <br/>}< br/> If (! Supermember) {<br/> for (VAR I = 0, j = superobjs. length; I <j; I ++) {<br/> superobj = superobjs [I]; <br/> for (methodname in superobj) {<br/> If (superobj [methodname] = overrided) {<br/> supermember = superobjs [I-1] [methodname]; <br/> return supermember. apply (this, argS ); <br/>}</P> <p> throw' if this step is completed, super () failed! '; <Br/>}
The "foreshadowing" mentioned above is designed for method overloading. Due to time constraints, I will post the source code first today, and add more details to the tutorials later (new ideas, old ideas are overturned .).
3. How is polymorphism?
Polymorphism means Multi-inheritance. However, I have not investigated the problem of polymorphism in depth. I only know that the FN. Apply/call method can be used to forcibly specify the this object pointer. Therefore, it is not recommended for polymorphism, that is:
Function a_class () {<br/> // Private local varialbies <br/> var localvar; </P> <p> // Private methods <br/> function privatemethod () {</P> <p >}< br/> function B _class () {<br/> a_class.call (this ); // This in a_class changes to the current B _class instance. <Br/> This. Foo = function () {</P> <p >}< br/>}
If this is "polymorphism", many people may think it is far-fetched. I agree, but I still think it is a convenient method and a way of thinking. However, I still feel that as a true polymorphism, it is not very relevant. Further research is needed.
Complete code with an inheritance method:
/** <Br/>. <Br/> * @ Param {function} son subclass <br/> * @ Param {function} base parent class <br/> */<br/> object. extend = (function () {<br/> function _ super () {<br/> var <br/> byexplicit = arguments [0] <br/>, byexplicit = byexplicit & byexplicit. length & byexplicit. callee <br/> // If explicit, it means arguments. caller === arguments (old) // true! <Br/> // if not explicit, it means get method by arguments. Caller. callee. <br/>, overrided = byexplicit? Arguments [0]: arguments. Caller. callee <br/>, the membername // member name remains unchanged. The name string used as the creden。 of the query member. <Br/>, supermember // found super member <br/>, superobjs = This. superobjs // parent class list <br/>, superobj // current parent class (not necessarily the target parent class) <br/>, argS = byexplicit? Array. Prototype. Slice. Call (arguments, 1): arguments; </P> <p> If (! Overrided) {<br/> debugger; <br/> error. throwerr ({<br/> MSG: "The args object must be input! "<Br/>, method: arguments. callee <br/>}); <br/>}</P> <p> // locate the member name first. <Br/> for (var I in this) {<br/> If (this [I] = overrided) {<br/> membername = I; <br/>}</P> <p> for (VAR I = 0, j = superobjs. length; I <j; -- j) {<br/> superobj = superobjs [J-1]; <br/> supermember = superobj [membername]; </P> <p> If (supermember) {<br/> return typeof supermember = 'function' <br/>? Supermember. Apply (this, argS) <br/>: supermember <br/>}< br/> If (! Supermember) {<br/> for (VAR I = 0, j = superobjs. length; I <j; I ++) {<br/> superobj = superobjs [I]; <br/> for (methodname in superobj) {<br/> If (superobj [methodname] = overrided) {<br/> supermember = superobjs [I-1] [methodname]; <br/> return supermember. apply (this, argS ); <br/>}</P> <p> throw' if this step is completed, super () failed! '; <Br/>}< br/> var queue = []; <br/> var timer = 0; </P> <p> function delayinherit (item) {<br/> var son = item [0], base = item [1]; <br/> object. extend (son, base); <br/> // OK, it's done! <Br/> debugger; <br/> // alert (typeof base) </P> <p >}</P> <p> function addqueue (son, Base) {<br/> queue. push ([son, base]); <br/> // If (! Timer) {<br/> // timer = setTimeout (function () {<br/> // array. each (queue, delayinherit, queue); <br/> //}, 2500/* This is a simulated value, not accurate */); <br/> //} <br/>}< br/> return function (son, Base) {<br/> // @ todo if not loaded, add to queue <br/> If (base & typeof (base )! = 'Function') {<br/> addqueue (son, base); <br/> return; <br/>}< br/> base = new base; </P> <p> If (! Base. _ super) {<br/> base. _ super = _ super; <br/>}</P> <p> If (! Base. superobjs) {<br/> base. superobjs = [base]; <br/>} else {<br/> base. superobjs. push (base); <br/>}< br/> son. prototype = base; // prototype inheritance! <Br/>}< br/>}) (); <br/>
I hope you can give me a little bit of help. I don't know if everyone is interested, but here I am making everyone laugh.