JavaScript面向对象编程:深入理解封装、继承与多态的经典例子

78 阅读3分钟

摘要:

本文将深入探讨JavaScript面向对象编程中的封装、继承和多态的概念,并通过丰富的代码示例来解释这些概念在实际开发中的应用。通过这些知识,我们将更好地利用JavaScript的面向对象编程特性,提高代码质量和复用性。

一、封装:

封装是将数据(属性)和操作数据的函数捆绑在一起,形成一个独立的实体。这有助于隐藏对象的内部实现细节,只暴露必要的接口。

示例1:

javascript复制代码
	function Car(make, model, year) {  

	  var car = this;  

	    

	  car.make = make;  

	  car.model = model;  

	  car.year = year;  

	    

	  car.getInfo = function() {  

	    return "品牌:" + car.make + ", 型号:" + car.model + ", 制造年份:" + car.year;  

	  };  

	}  

	  

	var myCar = new Car("Toyota", "Corolla", 2020);  

	console.log(myCar.getInfo()); // 输出:品牌:Toyota, 型号:Corolla, 制造年份:2020

在这个例子中,我们通过封装创建了一个Car对象,该对象具有make、model和year属性,以及一个用于获取车辆信息的getInfo方法。封装使我们能够隐藏对象的内部实现细节,只暴露必要的接口。

二、继承:

继承是一种机制,允许一个类继承另一个类的属性和方法。这使得我们可以创建更具体的类,继承更一般的类的属性和方法。

示例2:

javascript复制代码
	function Vehicle(make, model) {  

	  this.make = make;  

	  this.model = model;  

	}  

	  

	Vehicle.prototype.move = function() {  

	  return "车辆正在移动";  

	};  

	  

	function Car(make, model) {  

	  Vehicle.call(this, make, model); // 调用父类的构造函数  

	}  

	Car.prototype = Object.create(Vehicle.prototype); // 继承父类的原型链  

	Car.prototype.constructor = Car; // 修复构造器指向  

	Car.prototype.move = function() { // 重写父类的 move 方法  

	  return "汽车正在移动";  

	};

在这个例子中,我们创建了一个Vehicle类作为基类,并定义了一个move方法。然后,我们创建了一个Car类作为子类,继承了Vehicle类的属性和方法,并重写了move方法。通过继承,我们可以重用父类的代码,并且子类可以添加或覆盖父类的行为。

示例3:

首先,我们定义了一个Employee类作为基类:

javascript复制代码
	function Employee(name, position) {  

	  this.name = name;  

	  this.position = position;  

	  this.greet = function() {  

	    console.log("我是" + this.name + ",我的职位是" + this.position);  

	  };  

	}

然后,我们创建了两个子类:Manager和Engineer,分别继承了Employee类:

javascript复制代码
	function Manager(name, position, reports) {  

	  Employee.call(this, name, position); // 调用父类的构造函数  

	  this.reports = reports;  

	  this.promote = function() {  

	    console.log("提升员工");  

	  };  

	}  

	Manager.prototype = Object.create(Employee.prototype); // 继承父类的原型链  

	Manager.prototype.constructor = Manager; // 修复构造器指向  

	Manager.prototype.promote = function() { // 重写父类的 promote 方法  

	  for (var i = 0; i < this.reports.length; i++) {  

	    console.log(this.reports[i] + " 被提升为 " + this.position);  

	  }  

	};  

	  

	function Engineer(name, position, skills) {  

	  Employee.call(this, name, position); // 调用父类的构造函数  

	  this.skills = skills;  

	  this.specialty = function() {  

	    console.log("我的专长是 " + this.skills);  

	  };  

	}  

	Engineer.prototype = Object.create(Employee.prototype); // 继承父类的原型链  

	Engineer.prototype.constructor = Engineer; // 修复构造器指向  

	Engineer.prototype.specialty = function() { // 重写父类的 specialty 方法  

	  for (var skill in this.skills) {  

	    console.log(skill + ": " + this.skills[skill]);  

	  }  

	};

接下来,我们创建了一些实例并测试它们的行为:

javascript复制代码
	var john = new Engineer("John", "软件工程师", ["JavaScript", "HTML", "CSS"]);  

	var lisa = new Manager("Lisa", "项目经理", ["Emily", "Michael"]);  

	john.greet(); // 输出:我是 John,我的职位是软件工程师  

	lisa.greet(); // 输出:我是 Lisa,我的职位是项目经理  

	john.specialty(); // 输出:JavaScript: John, HTML: John, CSS: John  

	lisa.promote(); // 输出:Emily 被提升为软件工程师,Michael 被提升为软件工程师

在这个例子中,我们通过封装创建了Employee、Manager和Engineer对象,每个对象都有自己的属性和方法。Manager和Engineer类继承了Employee类,并添加了自己的属性和方法。我们还演示了多态性,即不同的对象可以调用相同的方法并表现出不同的行为。