轻松入门关于多态的详解
程序员文章站
2022-04-20 08:37:42
...
多态(Polymorphism)按字面的意思就是“多种状态”,同样的行为(方法)在不同对象上有不同的状态。
在OOP中很多地方都要用到多态的特性,比如同样是点击鼠标右键,点击快捷方式、点击桌面空白处、点击任务栏等弹出的菜单都是不同的。
在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/s9 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/s20 dog.run('20KM/h');//log:这只狗跑的速度有20KM/h21 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;
本系列还有最后一章,会把前几张讲的知识点通过一个案例整合在一起,让大家可以更好的消化吸收,大概会酝酿两周的时间;
大家有什么疑问可以留言或私信作者,作者尽量第一时间回复大家;
如果老司机们觉得那里可以有不恰当的,或可以表达的更好的,欢迎指出来,我会尽快修正、完善。
以上就是轻松入门关于多态的详解的详细内容,更多请关注其它相关文章!