How to understand object-oriented
Abstract is the prerequisite of encapsulation, inheritance and polymorphism. Reasonable abstraction comes from reasonable analysis and understanding of business topics. Reasonable abstraction should be self consistent and easy to understand about the relationship between composition and aggregation: the core difference is the life cycle difference. In the combination relationship, the whole and the individual are a whole. Without the whole, the individual is meaningless, produced and destroyed at the same time. In the aggregation relationship, some individuals can exist independently, even if they are separated from the arrangement. Don't abuse inheritance: inheritance is more of an object-oriented concept serving polymorphism: class and object
Distinguish between "Object-Oriented Programming" and "object-oriented programming language"
Object oriented is a programming specification or style. It is the basic unit of organizing code with classes and objects, and it is the cornerstone of code design and implementation through four characteristics of abstraction, encapsulation, inheritance and polymorphism
The object-oriented programming language is a syntax mechanism that supports classes and objects, and has ready-made syntax sugar (syntax mechanism). The programming language that can easily realize the four characteristics of object-oriented programming distinguishes between "process oriented programming" and "Object-Oriented Programming"
Process oriented programming:
With verbs as the main part, analyze the steps needed to solve the problem, and then use the function to implement these steps step by step, one by one when using.
Object oriented programming:
The main purpose of building objects is not to complete a step, but to describe the behavior of a thing in the whole step.
Object oriented: dog. Eat (bone) process oriented: eat (dog, bone)
Basic principles of object-oriented programming
Encapsulation: encapsulate abstract attributes and methods to hide information and protect data
/* * @title There are four ways to create an object implementation package * @method1 Object literal mode {Name: 'mark'u Zhang', key: 'value'} can only be created once, with poor reuse rate and more literal code redundancy * @method2 Built in constructor create var parson = new object(); parson. Name = "built in constructor create object" * @method3 Simple factory function function createObj (name){let obj = new Object(); obj.name = name; return obj} * @method4 Custom constructor */ function Person (name, agei) { // The attributes and methods contained in the constructor can understand part of the abstraction // Public public properties this.name = name; // Instances can be accessed directly through object points // Private private property let age = agei; this.getAge = function(){ return age; } this.setAge = function(a){ age = a; } } Person.prototype.show = function(){ return this.name ' This year' this.getAge() 'year'; } // The object must be created through the new keyword, otherwise this refers to the window object let p1 = new Person('Mark_Zhang',18) console.info(p1.name, p1.age) // Mark_Zhang undefined // Call object method (interface exposed by calling object) p1.setAge(30); console.info(p1.getAge()); // Call prototype method console.info(p1.show()) let p2 = new Person(); // Using object dynamics to add attributes p1.n = 'sunLine' console.info(p2.n) //sunLine /** * @title The difference between adding members through constructor and prototype * @Difference 1: all objects share the function (reference type) allocated by prototype method * @Difference 2: the attributes (basic types) allocated through the prototype method are independent * @Difference 2.2: we can also add through the. Syntax outside the class, because when instantiating an object, it will not execute the properties added through the. Syntax outside the class, so the instantiated object cannot access the objects and properties added by the. Syntax, only through the class. * @Difference 3: if you want all objects to use the same function, it is recommended to use the prototype method to add functions to save memory * @Difference 4: add methods to all objects through prototype, unable to access the private properties and methods of the class */
Abstract: how to hide the specific implementation of the method so that the caller only needs the functions provided by the relational method, and does not need to know how to realize these functions. Inheritance: one of the biggest benefits of inheritance is code reuse
Inheritance: the child class can use all the functions of the parent class and extend them. The process of inheritance is from general to special.
Class inheritance so-called class inheritance is the prototype method used to add methods to the prototype of the parent class, and then the prototype of the child class is an instantiated object of the parent class
// Declaring parent class let SuperClass function (){ let id = 1; this.name = ["inherit"]; this.superValue = function () { console.info("superValue is true") console.info('id---->',id) } } // Add method to parent class through prototype SuperClass.prototype.getSuperValue = function() { return this.superValue(); } // Declaring subclasses let SubClass = function () { this.subValue = function () { console.info("this is subValue") } } // Subclass inherits parent SubClass.prototype = new SuperClass(); // Add public method for subclass SubClass.prototype.getSubValue = function() { return this.subValue(); } let sub = new SubClass(), sub2 = new SubClass(); sub.getSuperValue(); // superValue is true sub.getSubValue(); // this is subValue console.info(sub.id) // undefined console.info(sub.name) // inherit sub.name.push('Class inheritance') console.info(sub2.name) // ['inheritance', 'class inheritance']
The core code is SubClass.prototype = new SuperClass(); The prototype object of a class, prototype object, is used to add common methods for the prototype of a class, but the class cannot directly access these methods. Only after the class is instantiated, the newly created object copies the properties and methods in the constructor of the parent class, and points prototype proto to the prototype object of the parent class. In this way, the subclass can access the public and protected properties and methods of the parent class. Meanwhile, the private properties and methods in the parent class will not be inherited by the subclass. Knock on the blackboard, as in the last section of the above code, use the method of class inheritance. If there is a reference type in the constructor of the parent class, it will be shared by all instances in the subclass. Therefore, if the reference type of an instance of a subclass is changed, it will affect the instances of other subclasses. Constructor inheritance
Formally, because of the above shortcomings, there is constructor inheritance. The core idea of constructor inheritance is SuperClass.call(this,id). Directly change the direction of this, so that the attributes and methods created through this are copied in the subclass. Because they are copied separately, each instantiated subclass does not affect each other. But it will cause memory waste
// SubClass.prototype = new SuperClass(); function SubClass(id) { SuperClass.call(this,id) }
The core idea of class inheritance constructor inheritance is that the prototype of subclass is the prototype of SuperClass.call(this,id) subclass instantiation object, whose phase and method point to the prototype of the parent
Each instantiated subclass is an individual, which does not affect each other. The subclasses may affect each other, and memory waste (the public properties and methods of the child columns are appended to the parent class through the prototype) is combined inheritance
In view of the above two inheritance methods, combinatorial inheritance takes the advantages of both, which not only avoids the waste of memory, but also makes each instantiated subclass not affect each other.
// Combinatorial inheritance // Declaring parent class let SuperClass = function(name) { this.name = name ; this.books = ['js','html','css'] } // Declare the f method on the parent prototype SuperClass.prototype.showBooks = function(){ console.info(this.books) } // Declaring subclasses let SubClass = function (name) { SuperClass.call(this,name); } // Subclass inherits parent (chain inheritance) SubClass.prototype = new SuperClass(); let subclass1 = new SubClass('java'); let subclass2 = new SubClass('php'); subclass2.showBooks(); subclass1.books.push('ios'); //["js", "html", "css"] console.log(subclass1.books); //["js", "html", "css", "ios"] console.log(subclass2.books); //["js", "html", "css"]
Parasitic combinatorial inheritance
Then the problem comes again. The method of combinatorial inheritance is good, but it will lead to a problem. The constructor of the parent class will be created twice (call() again, new again). So in order to solve this problem, parasitic combinatorial inheritance appears again. The key of the problem just now is that the constructor of the parent class has been created twice in the combination form of class inheritance and constructor inheritance, but we don't need to create the constructor of the parent class in class inheritance, we just want the child class to inherit the prototype of the parent class. So we first create a copy of the prototype of the parent class, then modify the constructor property of the child class, and finally set the prototype of the child class to work / / prototype Inheritance / / prototype inheritance is actually the encapsulation of class inheritance. The implementation function is to return an instance, and the prototype of the instance inherits the incoming o object
function inheritObject(o) { //Declare a transition function object function F() {} //The prototype of the transition object inherits the parent object F.prototype = o; //Returns an instance of a transition object whose prototype inherits the parent object return new F(); }
//Parasitic Inheritance / / parasitic inheritance is the second encapsulation of prototype inheritance, so that the prototype of the subclass is equal to the prototype of the parent. In the second encapsulation process, the inherited objects are extended
function inheritPrototype(subClass, superClass){ //Copy a prototype of the parent class and save it in the variable so that the prototype of p is equal to the prototype of the parent class var p = inheritObject(superClass.prototype); //Fix: the constructor property of the subclass was modified due to overriding the subclass prototype p.constructor = subClass; //Set the prototype of the subclass subClass.prototype = p; } //Defining parent class var SuperClass = function (name) { this.name = name; this.books = ['javascript','html','css'] }; //Defining parent prototype methods SuperClass.prototype.getBooks = function () { console.log(this.books) }; //Defining subclasses var SubClass = function (name) { SuperClass.call(this,name) } inheritPrototype(SubClass,SuperClass); var subclass1 = new SubClass('php')
Polymorphism: one of the biggest benefits is to improve the scalability and reusability of the code
encapsulation
What: hide information and protect data access. How: to expose limited interfaces and properties, the programming language is required to provide access control syntax. Why: improve code maintainability; reduce interface complexity and improve class usability.
abstract
What: hide the specific implementation. Users only need to care about the function, not the implementation. How: implemented by interface class or abstract class. Special syntax mechanism is not required. Why: improve the scalability and maintainability of the code; reduce the complexity and detail burden.
inherit
What: indicates the is-a relationship, which is divided into single inheritance and multi inheritance. How: programming languages are required to provide special syntax mechanisms. For example, "extensions" in Java and ":" in C. Why: solve the problem of code reuse.
polymorphic
What: the subclass replaces the parent and calls the implementation of the subclass at run time. How: programming languages are required to provide special syntax mechanisms. For example, inheritance, interface class, duck typing. Why: improve code scalability and reusability.
The key of 3W model is Why. Without Why, the other two have no meaning. From the four characteristics, we can see that the ultimate goal of object-oriented is only one: maintainability. Easy to expand, easy to reuse, reduce complexity and so on are all maintainability implementation methods.