JavaScript面向对象轻松入门之多态(demo by ES5、ES6、TypeScript)

  多态(Polymorphism)按字面的意思就是“多种状态”,同样的行为(方法)在不同对象上有不同的状态。
  在OOP中很多地方都要用到多态的特性,比如同样是点击鼠标右键,点击快捷方式、点击桌面空白处、点击任务栏等弹出的菜单都是不同的。

方法重写(override):

  即子类定义一个与父类名字相同的方法,以此覆盖父类方法,以此来实现不同的功能。

 1     function Animal(){}
 2     var AnimalP = Animal.prototype;
 3     AnimalP.eat = function(food){
 4         console.log(‘这个动物正在吃‘ + food);
 5     };
 6
 7     function Snake(){}
 8     var SnakeP = extend(Snake,Animal);//extend函数请看上一节
 9     /*snake没有对eat方法重写,继承的父类eat()方法*/
10     function Dog(){}
11     var DogP = extend(Dog,Animal);
12     DogP.eat = function(food){
13         /*对eat()方法重写*/
14         /*上一章讲过,也可以在这里通过 Animal.eat.call(this,food)调用父方法;*/
15         console.log("这只狗正在吃"+food);
16     };
17
18     function Cat(){}
19     var CatP = extend(Cat,Animal);
20     CatP.eat = function(food){
21         console.log("这只猫正在吃"+food);
22     };
23     var snake = new Snake();
24     snake.eat(‘老鼠‘);//log:这个动物正在吃老鼠
25     var dog = new Dog();
26     dog.eat(‘骨头‘);//log:这只狗正在吃骨头
27     var cat = new Cat();
28     cat.eat(‘鱼‘);//log:这只猫正在吃鱼

抽象类(abstract class):

  上面的代码中,Snake类没有实现自己的eat()方法,但有的时候我们希望子类一定要有某个方法(抽象方法),这样可以规范子类的行为,这时候就要用到抽象类,
  ES5、ES6都没有抽象类的概念的,所以我们只能通过模拟来实现,让我们接着上面的代码,假如我们要把Animal的eat()方法定义为抽象方法:

1     AnimalP.eat = function(food){
2         /*定义抽象方法(虚函数),如果子类没有重写这个方法,在执行这方法的时候就会抛出错误*/
3         throw ‘"‘ + this.constructor.name + "‘类没有eat()方法";
4     };
5     function Snake(){}
6     var SnakeP = extend(Snake,Animal);
7     var snake = new Snake();
8     snake.eat(‘老鼠‘);//throw:"Snake‘类没有eat()方法

方法重载(overload):

  我们一定写过这样的函数,根据传入的参数不一样(类型、参数个数),方法的运行结果也不一样:

1 var run = function(speed){
2         if(typeof speed == ‘number‘){
3             console.log(‘跑的速度有‘ + speed + ‘m/s‘);
4         }else if(typeof speed == ‘string‘){
5             console.log(‘跑的速度有‘ + speed);
6         }
7     }
8     run(15);//log:跑的速度有15m/s
9     run(‘20KM/h‘);//log:跑的速度有20KM/h

   但上面这样写明显代码难维护,可以把run方法作为一个接口,根据参数的类型执行不同方法,用在类中就向下面一样:

 1     function Dog(){}
 2     var DogP = Dog.prototype;
 3     DogP.run = function(speed){
 4         if(typeof speed == ‘number‘){
 5             this._runNumber(speed);
 6         }else if(typeof speed == ‘string‘){
 7             this._runString(speed);
 8         }else{
 9             throw ‘参数不匹配‘;
10         }
11     }
12     DogP._runString = function(speed){
13         console.log(‘这只狗跑的速度有‘ + speed);
14     }
15     DogP._runNumber = function(speed){
16         console.log(‘这只狗跑的速度有‘ + speed + ‘m/s‘);
17     }
18     var dog = new Dog();
19     dog.run(15);//log:这只狗跑的速度有15m/s
20     dog.run(‘20KM/h‘);//log:这只狗跑的速度有20KM/h
21     dog.run([]);//throw:参数不匹配

  这就是方法重载的模拟,但实际上,ES5、ES6、typescipt都不支持语法上的方法重载,typescipt也只是支持函数重载。
  这是多态的另一种实现方式。

Demo by ES6:

 1     class Animal{
 2         eat(food){
 3             throw ‘"‘ + this.constructor.name + "‘类没有eat()方法";
 4         }
 5     }
 6     class Snake extends Animal{}
 7     class Dog extends Animal{
 8         eat(food){
 9             console.log("这只狗正在吃"+food);
10         }
11     }
12     class Cat extends Animal{
13         eat(food){
14             console.log("这只猫正在吃"+food);
15         }
16     }
17     let snake = new Snake();
18     snake.eat(‘老鼠‘);//throw:"Snake‘类没有eat()方法
19     let dog = new Dog();
20     dog.eat(‘骨头‘);//log:这只狗正在吃骨头
21     let cat = new Cat();
22     cat.eat(‘鱼‘);//log:这只猫正在吃鱼

Demo by TypeScript:

 1 abstract class Animal{//定义抽象类Animal
 2     constructor(){}
 3     abstract eat(food: string){}
 4     /*定义抽象方法eat(),并且限定传入的参数类型是string,
 5     还可以定义返回值,接口等,如果子类不符合限定的规范,编译的时候就会报错。
 6     */
 7 }
 8 class Snake extends Animal{}//报错,无法通过编译,因为没有定义eat()抽象方法
 9 class Dog extends Animal{
10     eat(food: string){
11         console.log("这只狗正在吃"+food);
12     }
13 }
14 class Cat extends Animal{
15     eat(food: string){
16         console.log("这只猫正在吃"+food);
17     }
18 }
19 let dog = new Dog();
20 dog.eat(‘骨头‘);//log:这只狗正在吃骨头
21 let cat = new Cat();
22 cat.eat(‘鱼‘);//log:这只猫正在吃鱼

后话

  如果你喜欢作者的文章,记得收藏,你的点赞是对作者最大的鼓励;

  面向对象的主要知识点在这里就讲完了,这些东西仅仅是基础,我讲的肯定不够完善,仅仅是为了让大家快速入门,建议大家有时间的话还是系统的看书学习一下js OOP;

  本系列还有最后一章,会把前几张讲的知识点通过一个案例整合在一起,让大家可以更好的消化吸收,大概会酝酿两周的时间;

  大家有什么疑问可以留言或私信作者,作者尽量第一时间回复大家;

  如果老司机们觉得那里可以有不恰当的,或可以表达的更好的,欢迎指出来,我会尽快修正、完善。

时间: 2024-12-29 15:01:35

JavaScript面向对象轻松入门之多态(demo by ES5、ES6、TypeScript)的相关文章

JavaScript面向对象轻松入门之封装(demo by ES5、ES6、TypeScript)

本章默认大家已经看过作者的前一篇文章 <JavaScript面向对象轻松入门之抽象> 为什么要封装? 封装(Encapsulation)就是把对象的内部属性和方法隐藏起来,外部代码访问该对象只能通过特定的接口访问,这也是面向接口编程思想的一部分. 封装是面向对象编程里非常重要的一部分,让我们来看看没有封装的代码是什么样的: 1 function Dog(){ 2 this.hairColor = '白色';//string 3 this.breed = '贵宾';//string 4 this

JavaScript面向对象轻松入门之概述(demo by ES5、ES6、TypeScript)

写在前面的话 这是一个JavaScript面向对象系列的文章,本篇文章主要讲概述,介绍面向对象,后面计划还会有5篇文章,讲抽象.封装.继承.多态,最后再来一个综合. 说实话,写JavaScript面向对象的文章实在是太多了,网上一搜一大堆,很多书里面也介绍的很详细.但作者当初在学习面向对象的时候还是非常困难,特别是在习惯了面向过程编程的情况下,不知道大家有没有这个感受. 作者分析了一下其中的原因,恐怕是因为里面涉及的概念太多:原型.原型链.继承.this.constructor.call等等,这

JavaScript面向对象轻松入门之继承(demo by ES5、ES6)

继承是面向对象很重要的一个概念,分为接口继承和实现继承,接口继承即为继承某个对象的方法,实现继承即为继承某个对象的属性.JavvaScript通过原型链来实现接口继承.call()或apply()来实现实现继承. 接口继承的实现在ES5中是比较麻烦,在其它OOP语言中一个extends关键字就可以实现,但在ES5中要通过原型链去模拟,非常难理解,对初学者很不友好,并且有好几种接口继承的方式.本文为了对初学者更友好,并不打算让读者了解接口继承的原理,而是直接把接口继承实现方法封装成一个函数,大家只

javascript面向对象:继承、多态

继承 js中同样可以实现类的继承这一面向对象特性,继承父类中的所有成员(变量和属性),同时可扩展自己的成员,下面介绍几种js中实现继承的方式: 1,对象模仿:通过动态的改变 this 指针的指向,实现对父类成员的重复定义,如下: function ClassA(paramColor) { this.color = paramColor; this.sayColor = function() { alert(this.color); } } function ClassB(paramColor,

JavaScript面向对象编程入门

来源极客网 1 function Person() { 2 var _this = {} //创建一个空的对象,接着我们利用这个"空的对象"承载Person的属性和方法 3 _this.sayHello = function(){ 4 alert("PHello"); 5 } 6 return _this; 7 } 8 9 function Teacher_1() { 10 var _this = Person();//注意这里的语法小括号 11 return _t

【转】「译」ES5, ES6, ES2016, ES.Next: JavaScript 的版本是怎么回事?

ES5, ES6, ES2016, ES.Next: What's going on with JavaScript versioning? Posted by Hux on September 22, 2015 JavaScript 有着很奇怪的命名史. 1995 年,它作为网景浏览器(Netscape Navigator)的一部分首次发布,网景给这个新语言命名为 LiveScript.一年后,为了搭上当时媒体热炒 Java 的顺风车,临时改名为了 JavaScript (当然,Java 和

Swift轻松入门——基本语法介绍和详细地Demo讲解(利用WebView打开百度、新浪等网页)

本文主要分为两个部分,第一部分介绍Swift的基本语法,第二部分讲解一个利用WebView来打开百度.sina等网页的小demo,如果对swift的语法不感兴趣的同学可以直接跳到第二部分来感受下Swift的魅力-(本文的demo源码已上传至github:https://github.com/iOSGeek0829/XSurfing) 一.Swift常用语法 Swift是Apple去年推出的一门新的语言,基于C和Objective-C,而没有C的一些兼容约束,它采用了安全的编程模式和添加现代的功能

JavaScript 面向对象程序设计(下)&mdash;&mdash;继承与多态 【转】

JavaScript 面向对象程序设计(下)--继承与多态 前面我们讨论了如何在 JavaScript 语言中实现对私有实例成员.公有实例成员.私有静态成员.公有静态成员和静态类的封装.这次我们来讨论一下面向对象程序设计中的另外两个要素:继承与多态. 1 又是几个基本概念 为什么要说又呢? 在讨论继承时,我们已经列出了一些基本概念了,那些概念是跟封装密切相关的概念,今天我们要讨论的基本概念,主要是跟继承与多态相关的,但是它们跟封装也有一些联系. 1.1 定义和赋值 变量定义是指用 var a;

[JavaScript] JavaScript 面向对象设计 (3) : 多态与界面篇

在前一篇中我们介绍了基础的 JavaScript 继承实践法,透过 Object.prototype 我们可以自由决定对象要继承自哪个对象,也可以扩充对象目前现有的属性和方法 (和 C# 的 Extension Method 有异曲同工之妙),在本篇中,我们要来介绍面向对象的另一个特性:多态 (Polymorphism). 在前一篇中我们介绍了基础的 JavaScript 继承实践法,透过 Object.prototype 我们可以自由决定对象要继承自哪个对象,也可以扩充对象目前现有的属性和方法