代码改变世界

面向对象

2015-06-22 20:28  在web学习路上  阅读(382)  评论(0)    收藏  举报

  现在看各种招聘的要求都是需要应聘者有面向对象的开发经验,所以js中面向对象的技术相当重要,需要熟悉掌握。

首先对象叫什么,什么叫面向对象的编程,什么是面向对象?百度一下。吧啦吧啦说了一堆对面向对象的解释,最后总结到一句:面向对象是一种对现实世界理解和抽象的方法”。“起初,面向对象是专指在程序设计中采用封装、继承、多态等设计方法”。这三个词我感觉学习了一些js基本概念后,应该是很容易就能理解了。

 

封装,可以简单理解为,将需要做的事情定义成为一个具有参数的函数,只对外提供传参数的接口,方便多次调用来处理某些参数不同,但实际过程一样的事情。

 

function fn(a){alerta;}; 最简单的封装,传什么弹什么。

 

类和继承,在js里面的实现可以通过构造函数,原型来实现。将需要继承的属性,方法写在原型上,创建出来的实例对象就有个属性指向构造函数的原型,能够获取到上面的属性和方法。

 

functionPerson(name){

 

this.name =name;

 

}

 

Person.prototype.getName= function(){

 

alert(this.name);

 

};

 

var person1 =new Person(‘Paul’);

 

这个就是最简单的继承了。新对象person1继承了PersongetName方法。当然如果要是想问为什么这样就能继承,这个我也说不清楚,估计只能去js的底层代码去找答案,js就是有这种特性。我,作为新人,感觉现在不要去考虑“为什么能”的问题,目前学习阶段最重要的是掌握js是“怎么做到”的,我们要了解上面写了继承的代码,js究竟做了哪些事情呢。这个需要了解的东西就多了:函数声明;原型(定义,特性,类型….);new操作符;函数表达式;this指向,如果子类继承父类,再学点callapply等改变指向的方法等等等…..但是都已经开始考虑面向对象了,这些基础部分应该十分也能说个六七分吧。

 

 

 

多态性的定义是:同一操作作用于不同的类的实例,将产生不同的执行结果。很明显啊,如上面的例子。

 

var person1 =new Person(‘Paul’);

 

var person2 =new Person(‘Jack’);

 

person1.getName();    //’Paul’

 

person2.getName();     //’Jack’

 

调用了同样的方法,但是结果不同,实例是多态的,结果也是多态的。当然我这里只是举了最简单的例子,貌似还有什么静态多态,动态多态什么的,我没别的语言基础,确实也还搞不明白。

 

 

 

好了。现在看到这里,再思考下面向对象的概念:对现实世界理解和抽象的方法。什么现实世界?简单说就是我们看到的东西。对现实的理解和抽象?就是将看到的同类的东西概括出来。

 

比如,我们走在大街上,看到一辆红色兰博基尼以180km/h的速度的飞驰而过。然后我一拐弯,又看到一辆黄色的夏利停在路边。好了,有个需求,描述一下看到的东西。

 

var car1 = newObject();

 

car1.name = ‘兰博基尼’;

 

car1.speed =180;

 

car1.color =‘red’;

 

car1.action =function(){

 

return( ‘’+this.speed + ‘km/h的速度前行’);

 

}

 

 

 

var car2 = newObject();

 

car2.name = ‘夏利’;

 

car2.speed = 0;

 

car2.color = ‘yellow’;

 

car2.action =function(){

 

return( ‘’+this.speed + ‘km/h的速度前行’);

 

}

 

好吧,其实谁都知道,这样肯定写麻烦了,应该封装起来,方便下次调用。

 

function newCar(name,speed,color){

 

var car = newObject();

 

car.name =name;

 

car.speed =speed;

 

car.color =color;

 

car.action =function(){

 

return( ‘’+this.speed + ‘km/h的速度前行’);

 

}

 

return car;

 

}

 

恩,现在方便多了,每次见到个新车,只要传入参数运行一次就行了。写到这里,我们先做一件事情,回顾下我们刚才写上面的代码,还有封装了一个函数时候,我们的思维过程。我看到了一辆车,车有车的名字、颜色、速度,行为。我每次描述一辆新车,我都要重新全部描述一遍,所以我封装了一个函数来方便描述。突然一想,咦我这也不是描述了一类事物么,都是车,这不也是类么,而且,调用方法的结果也是不一样,多态的啊?哈哈,说真的,看面向对象的类,还有这里的这个“类”,我一开始也纠结了好久,有什么区别,都是描述的一类东西啊。

 

这里先不考虑区别,我们来看下面向对象的写法,那就是直接创建类。

 

function Car(){

 

this.name =name;

 

this.speed =speed;

 

this.color =color;

 

}

 

Car.prototype.action= function(){

 

return( ‘’+this.speed + ‘km/h的速度前行’);

 

}

 

我们现在来考虑下我们写这段代码时候的思维过程。我需要描述所见到的车,于是我就想,有一类东西叫车,车有车名,颜色,速度,还有行为。这些属性都是不同的车是不同的,但是所有车都具有这些属性。所以我就将这些属性概括出来,然后创建成了类的属性。

 

 

 

好的,到这里,我们先不比较代码,我们先来比较下我们写上面两种代码时候的思维过程。第一种:

 

我有个需求(描述见到的车)——见到兰博基尼我开始描述(兰博基尼,红,180,正在跑)——见到夏利我开始描述(夏利,黄,0,以0的速度在跑)——后面还可能见到更多车

 

第二种:

 

我有个需求(描述见到的车)——我先将想了下车有什么属性(车是一类东西,有颜色,名字,速度,行为)——我封装了一个构造函数——描述见到车调用即可

 

 

 

写到这里,我觉得,很多人最大的疑问应该是,第一种方法明明是我封装了函数,然后见到一个新车就调用一次就行啊,你怎么没把封装的函数写进去呢?你写的第二种本质上也是封装了一个函数,见到一个车就new一次啊。

 

好的,这里我们再仔细想一下,我们封装第一种函数的时候,我们想的是什么。我知道很多人都可以做到先封装函数然后调用来提高效率,但是请仔细想一下“封装函数的时候,我们到底想的是什么?”。我需要描述看到的车,我看到了兰博基尼,但我为了方便,开始封装函数:兰博基尼有自己的颜色,封装进来;兰博基尼有自己速度,封装进来….好了,将属性概括完了,函数封装完了,以后调用就行了。

 

很明显,第一次的时候,我们的着眼点是单辆车,后面的函数封装newCar其实也是从单个或者2个具体的实例中概括出来的,是我们为了应付不同实例车的同一属性的不同属性值,为了方便而封装的。我们的思维是,先找到实例属性值不同的属性(颜色,速度等等),然后概括出来封装。

 

第二次的时候,我们着眼点是车是一类东西,所有的车都有颜色,速度等等共有的属性。一开始我们就着手概括起一类事物的共有的属性来了。

 

好了,是不是看清楚了,我们思维的出发点是不同的。一种是少数实例上属性值不同的属性,另一种是概括出一类事物都具有的属性。

 

 

 

其实,写了这么多,我总感觉实际上普通的过程式的函数,能够概括出来封装起来,就已经有了面向对象的雏形了,也只能叫雏形,因为并没有真正面向对象写法的优点。就像上面的newCar函数,虽然是从面向过程的单个车描述概括出来的,但它其实也可以描述部分车了。写到封装这种程度,其实我感觉应该是处于一种面向过程到面向对象的过渡阶段了。我们要做到面向对象思维,就是要改变我们看事物的想法。再举个例子,描述运动。面向过程的思维是:物体要动起来,运动的物体不同,速度不同,距离不同。。。。而面向过程的思维是:物体运动,需要具有的属性有运动的对象,速度,距离。。。。这下应该明白很多了吧。放到编程中去就是,思维出发点,一个是多个实例不同的属性,另一个就是类的属性。