JS没有类似继承,而是通过原型委托的方式实现对象与对象间的继承。
1、动态类型语言和鸭子类型
编程语言按数据类型大体可分两类:静态类型语言,动态类型语言(如JS)。
静态:编译时就已确定变量的类型;
动态:变量类型要到程序运行时,待变量被赋予某个值之后,才会具有某种类型。
鸭子类型(duck typing):走起来像鸭子,叫起来也是鸭子,那它就是鸭子。
只关注对象的行为(HAS-A组合),而不关注对象本身(IS-A继承)----(USE-A依赖)
“面向接口编程,而不是面向实现编程”----一个对象如果有pop和push方法,且这些方法提供了正确的实现,就可以被当做栈来使用
2、多态(polymorphism,复数形态)
2.1----定义
同一操作,作用于不同的对象上面,可以产生不同的解释和不同的执行结果。消息1,给对象1和对象2,分别给出不同的反馈1和反馈2 。
var makeSound = function(animal) { if (animal instanceof Duck) { console.log('gagaga'); }else if(animal instanceof Chicken) { console.log("jijiji"); } }; var Duck = function(){}; var Chicken = function(){}; makeSound(new Duck()); makeSound(new Chicken());
做什么--动物都会叫---不变的事物----隔离
谁去做及怎样去做---不同类型动物具体怎么叫---可变的食物---封装
修改代码??NO
增加代码??OK?
var makeSound = function(animal) { animal.sound(); }; var Duck = function(){}; Duck.prototype.sound=function() { console.log("嘎嘎嘎"); }; var Chicken = function(){}; Chicken.prototype.sound=function() { console.log("咯咯咯"); }; makeSound(new Duck()); makeSound(new Chicken());
2.2-----类型检查和多态:
JAVA: String str; str = "abc"; str = 2; // 报错
解决类型检查问题,静态类型的面向对象语言通常被设计为可以向上转型:当给一个类变量赋值是,这个变量的类型既可以使用这个类本身,也可以使用这个类的超类。
eg:描述“一只麻雀/喜鹊在飞” --- 忽略他们的具体类型,可以说---“一只鸟在飞”
2.3-----使用继承得到多态效果
继承通常包括实现继承和接口继承。(java)
2.4-----JS的多态
多态的思想实际上是把“做什么”,“谁去做”分离开。--消除类型之间的耦合关系。
JS作为一门动态类型语言,在编译时没有类型检查的过程,既没有检查创建的对象类型,又没有检查传递的参数类型。以上makeSound函数里传递的duck对象或chicken对象做参数都可以。SO,某一种动物能否发出叫声,只取决于它有没有makeSound方法,而不取决于它是否是某种类型的对象,这里不存在任何程度上的“类型耦合”。
2.5-----多态在面向对象程序设计中的作用
《重构:改善既有代码的设计》Martin Fowler
多态的根本好处在于,你不必知道对象是什么类型,然后根据得到的答案调用对象的某个行为---你只管调用该行为就是了,其他的一切多态机制都会为你安排妥当。
in other words,多态最根本的作用就是,通过把过程化的条件分支语句转化为对象的多态性,从而消除这些条件分支语句。
导演Action之后,群众演员,道具师,主角都知道自己要做什么。而面向过程,就需要导演在开拍之前,去确认这个人是啥类型,然后告诉他们要做什么。
每个对象应该做什么,已经成为了该对象的一个方法,被安装在对象的内部。
将行为分布在各个对象中,并让这些对象各自负责自己的行为,正是面向对象设计的优点。