面向对象知识点总结
面向对象与面向过程有什么区别?
答:面向过程:强调的是每一个功能实现的具体步骤。
面向对象:基于面向过程,强调的是对象,然后由对象去调用功能。
举例:洗衣服
面向过程:把衣服脱下--找一个盆--放点洗衣粉--加点水--把衣服扔进去--搓一搓--清洗衣服--拧干--晾起来
面向对象:把衣服脱下--打开全自动洗衣机--扔进去--一键即可--晾起来
(毕向东)面向对象其实是一种思考问题的思想,早期的思想是面向过程,通过不断的演化,到了现在的面向对象。
我们举一个例子,把什么是面向过程,什么是面向对象说一下:
把大象放进冰箱里,分几步?三步!
第一步:把冰箱门打开。
第二步:把大象放里面去。
第三步:把冰箱门关上。
注意:我们把冰箱门打开,把大象放进去,把冰箱门关上,我们在强调什么?我们在强调过程。打开的动作,存储的动作,关闭的动作。这就是一个标准的面向过程的思想,我们注重的是过程,注重的是过程当中所涉及到的行为,也就是功能。打开功能,存储功能和关闭功能。过程强调的是行为、动作或者功能。
那么将它转换成面向对象又是什么样的呢?
大家分析一下,我们发现,无论是打开、存储还是关闭。它们都是冰箱这类事物所具备的行为,因为你操作的始终都是冰箱。这个时候就把这个思想给转变了。既然打开、存储和关闭都是冰箱的一个行为,我们只要操作冰箱中所具备的功能就可以的话,我们就把这些行为全部定义到冰箱当中,那么冰箱是不是一个实实在在存在的东西啊?这个我们把它称之为对象。而现在我再看到的东西就不是打开、存储和关闭了。我看到的就只有一个事物,就是冰箱。而冰箱里面有打开、存储和关闭的动作。
来画个图看一下:
总结:
面向对象到底是什么呢?
第一 面向对象是一种思考问题的方式,是一种思想。
第二 面向对象将复杂的事情变简单了。面向过程需要面向好多的动作,而面向对象只需要
面向一个事物就可以了。
第三 面向对象让我们的角色做了转变,从原来的执行者过渡到了指挥者。
第四 面向对象基于面向过程。
面向对象(生活举例)
例1:
你去电脑城买电脑,买电脑的时候,按照一般正常的思路是这样的:无论是买笔记本还是台式机,首先我们要去查阅一下资料,比如说CPU的型号、缓存、参数、硬盘、显卡、内存等等,还要查一下价格,为什么查啊?是怕被人骗!前期,你就做了一个查阅资料的动作。查完之后,你去电脑城,然后挨个商家去问价格啊,硬件啊等等,你就做了一个咨询的动作。最后买的时候,你还要砍价,还没砍过人家,最后还被骗了!你做了这么多准备工作,为什么还会被骗呢?就是因为你不懂!就靠花两天查阅了一下资料,就懂了?那不太现实!那么在你不懂的情况下,你为了不上当受骗,你该怎么做呢?找个懂行的!假如我特别懂电脑,我跟着你去,那么,咨询,砍价,监督装机这些动作是不是都是我来完成,而你只需要做的就是付钱。
咱们来看看,刚开始你去买电脑,你很痛苦,因为你要走整个过程,而这个过程你不熟。而后期你为了避免一些麻烦,你找了懂行的我,那你是不是使用了我的专业识别硬件的功能,专业砍价的功能,你为什么要找我啊?是因为我具备这些功能,这就叫找对人了!而我对于你来讲,我就是那对象,你就是在面向我这个对象。
那么,第一,你买电脑这件事是不是从复杂变得简单了?第二,你是不是从执行者变成指挥者了?你只要指挥我的专业识别硬件的功能,指挥我的专业砍价的功能就可以了!
例2:
一个老板,接了一个活,一个300万的软件开发的项目,但是呢?这位老板本身并不具备软件开发的能力,他要怎么做呢?他可不可以自己做?现学?可以,因为项目就是人做出来的嘛!于是乎,这个老板现学软件开发,终于,5年时间,他把那个项目做出来了,可事实是那个给钱的公司早就黄了!这是不是不靠谱啊?那这个老板该怎么做?他聘请了一批程序员,说这有个项目,你们给我做出来,程序员是不是专业啊?那这没那个老板什么事了,他就去喝茶,玩去了!对这个老板来说,开发软件这个事情是不是从复杂变得简单了?他是不是从一个执行者转换成了指挥者?这写专业程序员对老板来说就是对象,老板面向这些对象,调用这些对象本身具有的功能来实现了自己的目的!这就是面向对象!
例3:(面试的时候用)
什么是面向对象?
面向对象是一种思考问题的方式,是一种思想;面向对象能让复杂的问题简单化;面向对象让我们的角色做了转变,从原来的执行者过渡到了指挥者;面向对象基于面向过程。面向对象有三大特征:封装、继承、多态。举个具体的例子:
其实,面试官,你现在就是用面向对象的思想思考问题,公司有招人的需求,是因为公司的业务量比较大,代表着公司正在蒸蒸日上的发展。你在用面向对象的思想在思考问题,你需要找一些有专业编程经验的人来帮你完成公司的工作,而我就是那个对象,我就具备那个专业编程的功能,你找我就对了!你就是在指挥我做事情,你就是在使用我的专业编程功能为公司创造价值。当然,我不仅具备专业编程的功能这个基本的需求,我还具备比如说表达能力啊,管理能力等功能,你日后还可以让我当个小组长什么的,这完全没有问题!
面向对象的基本思想,给大家举这几个基本的例子解释一下!
注意:对象不仅仅指人,万事万物皆对象!这就是说你所看到的,你所想到的概念都可以看作是一个对象!
那么,落实到程序上是怎么样的呢?
我们写程序的时候,我们其实不是先要定义功能,而是先要面向对象。我要面向谁啊?我要面向这个对象,这个对象里面需要什么功能,我就把功能写到这个对象里面去,封装起来。下次我要用到这个功能的时候,我先去找这个对象,对象一找到,功能就找到了。在解决问题的时候,你们要做的是,不是先自己写,而是去找java当中是不是已经提供好了相对应的对象?如果有,不多说,直接拿过来用,这样是不是就简单化了?它里面的功能是怎么实现的,和我没关系,我只要拿到相对应的需求结果就行了!如果java当中没有我们需要的对象的话,那我们就自己造一个对象,把功能定义到里面去。因为你造完之后,这个对象,你能用,别人是不是也能用?就是这个道理!
面向对象有哪些特征?
答:封装、继承、多态。
什么是继承?
答:继承是面向对象中的一个非常重要的特性。通过继承,子类可以使用父类中的一些成员变量与方法,从而能够提高代码的复用性,提高开发效率。在Java语言中,被继承的类叫基类或父类,继承基类或父类的类叫派生类或子类。继承是通过extends关键字来实现的,使用格式为:class 子类名 extends 父类名。
继承主要有如下几个特性:
1)Java语言不支持多重继承,也就是说,子类至多只能有一个父类,但是可以通过实现多个接口来达到多重继承的目的。
2)子类只能继承父类的非私有(public与protected)成员变量与方法。
3)当子类中定义的成员变量和父类中定义的成员变量同名时,子类中的成员变量会覆盖父类的成员变量,而不会继承。
4)当子类中的方法与父类中的方法有相同的函数签名(相同的方法名,相同的参数个数与类型)时,子类将会覆盖父类的方法,而不会继承。
常见笔试题:
下列有关继承的说法中,正确的是(B)
A.子类能继承父类的所有方法和状态 B.子类能继承父类的非私有方法和状态
C.子类只能继承父类public方法和状态 D.子类能继承父类的方法,而不是状态
什么是多态?
答:多态性在面向对象中是一个非常重要的概念,在Java中主要有以下两种体现形式:
(1)方法的重载和重写。方法的重载又叫编译时多态,方法的重写又叫运行时多态。这时的多态表示当同一操作作用在不同对象时,会有不同的语义,从而会产生不同的结果,例如,同样是执行“+”操作,“3+4”用来实现整数相加,而“3”+“4”却实现了字符串的连接。
(2)对象的多态性。同一个对象(事物),在不同时刻体现出来的不同状态。
向上转型(子类对象→父类对象)
向下转型(父类对象→子类对象)。
对于向上转型,程序会自动完成,而对于向下转型时,必须明确地指明要转型的子类类型。
方法重写和方法重载的区别?方法重载能改变返回值类型吗?
方法重写:在子类中,出现和父类中一模一样的方法声明的现象。
方法重载:同一个类中,出现的方法名相同,参数列表不同的现象。
方法重载能改变返回值类型,因为它和返回值类型无关。
Override:方法重写
Overload:方法重载
抽象类和接口的区别?
答:
接口的关键字是interface;抽象类的关键字是abstract。
接口中的方法全是抽象方法,没有实现;抽象类中的方法可以有部分非抽象方法。
接口需要被实现(用implements),一个类可以实现多个接口;抽象类只能被继承(用extends),一个类只能继承一个抽象类。
接口中定义的成员变量默认为public static final,其所有方法都是public、abstract的;抽象类中定义的成员变量默认为default,当然也可以被定义为private、protected和public,抽象类中的抽象方法(其前有abstract修饰)不能用private、static、sychronized、native等访问修饰符修饰。
常见笔试题:
1. 下列关于接口的定义中,正确的是()
A.void methoda(); B.public double methoda()
C.public final double methoda() D.static void methoda(double d1);
E.protected void methoda(double d1) F.int a
G.int b=1
答案:A、B、G。接口中的方法只能用关键字public和abstract来修饰,因此CDE都是错误的。接口中的属性默认都为public static final,由于属性被final修饰,因此它是常量,常量在定义时就必须初始化,因此F是错误的。
2. 下列说法中,正确的是(B)
A.声明抽象方法大括号可有可无 B.声明抽象方法不可写出大括号
C.抽象方法有方法体 D.abstract可修饰属性、方法和类
答案:B。抽象方法不能有方法体,同理也就不能有大括号。abstract只能用来修饰类与方法,不能用来修饰属性。
如何获取父类的类名?
答:this.getClass().getSuperclass().getName()。
注意:this.getClass().getName()和super.getClass().getName()获取到的是当前运行时类的名称。
为什么?
因为Java语言总任何类都继承自Object类,getClass()方法在Object类中被定义为final与native,子类不能覆盖该方法。因此this.getClass和super.getClass()最终都调用的是Object中的getClass()方法。而Object的getClass()方法的释义是:返回此Object的运行时类。
this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
this:代表当前类的对象引用
super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)
场景:
成员变量:
this.成员变量
super.成员变量
构造方法:
this(...)
super(...)
成员方法:
this.成员方法
super.成员方法
常见笔试题:
class Base{
public Base(){
System.out.println("Base");
}
}
class Sub extends Base{
public Sub(){
System.out.println("Sub");
super();
}
}
public class Test{
public static void main(String[] args){
Base s = new Sub();
}
}
答案:编译错误。当子类构造函数需要显示调用父类构造函数时,super()必须为构造函数中的第一条语句,因此正确的写法如下:
public Sub(){
super();
System.out.println("Sub");
}
|
this指向
今天就和大家来探讨一下在js面向对象中的这个this的指向问题,
一般来讲在函数中this的指向是当前函数的拥有者,也就是说当前谁这个函数,那么这个this就指向谁.
例:这里有一按钮 btn
<input type ="button" id ="btn">document.getElementById('btn').onclick = function(){alert(this)//input}此时this是指向按钮 btn
第一种情况:
在面向对象中用了定时器
这里有一个对象;
function fn(){this.a= 1;//fn中的一个属性}fn.prototype.show = function(){alert(this.a)//fn原型链上的一个方法}var obj = new fn();//实例化的时候obj.show();//执行以下show()方法,弹出值为1
现在我们给这个对象加一个定时器看会怎么样
function fn(){this.a= 1;//fn中的一个属性setInterval(this.show,1000)//定时器}fn.prototype.show = function(){alert(this.a)//fn原型链上的一个方法 弹出a的值}var obj = new fn();//实例化
这个时候函数在执行的时候 弹出值为undefined
为什么那?
现在我们来看一下这个this 是指向谁的
function fn(){this.a= 1;//fn中的一个属性setInterval(this.show,1000)//定时器 弹出值是window}fn.prototype.show = function(){alert(this)}var obj = new fn();//实例化
原因就是定时器调用的函数都是指向`window`,所以我们这里弹出的都是`undefined` 因为window上没有`show()`这个方法;
现在原因找到了怎么解决那,其实很简单;
我们不要改变他的所属关系就好,就像这样:
function fn(){var _this = this //将我们原来的this赋给_thisthis.a= 1;//fn中的一个属性//将原来的方法包一下目的就是不改变他们的所属关系setInterval(function(){_this.show();},1000)//定时器}fn.prototype.show = function(){alert(this.a)//fn原型链上的一个方法 弹出的就是:1//因为上面我们已经将this赋给_this了,所以此时this的指向就不在是window了,而是指向了obj}var obj = new fn();//实例化
好~~第一种情况我们已经接解决了,下面我们来看第二种情况,,,
第二种情况:
面向对象添加了事件的,
例:这里有一个按钮
<input id="btn" type="button" value="按钮"/>function fn(){this.a = 1;document.getElmentById('btn').onclick = this.show;//弹出值为undefined 此时的this指向是input,而input是没有 show()方法,所以undefined}fn.prototype.show = function(){alert(this.a)}new fn()
怎么解决那?
方法和含有定时器的一样都是在原来的方法外面在套一层 并未把this重新附一下值;
function fn(){var _this = thisthis.a = 1;document.getElmentById('btn').onclick = function(){_this.show();//弹出值为1}}fn.prototype.show = function(){alert(this.a)}new fn()
其实这两种情况的解决方式都用到了闭包,
将函数外面的this给存一下,然后通过闭包传递this
function fn(){var _this = this //存一下thisthis.a= 1;setInterval(function(){_this.show();//里面调用},1000)