一、面向对象和面向过程
- 面向过程(POP,Procedure Oriented Programming)
强调的是功能行为,以函数为最小单位,考虑怎么做。 - 面向对象(OOP,Object Oriented Programming)
将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。程序员从面向过程的执行者转化成面向对象的指挥者。
二、面向对象的三大特征
1.封装
我们程序设计追求“高内聚,低耦合”。
- 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
- 低耦合 :仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
2.继承
- 为什么要有继承?
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
此处的多个类称为子类( 派生类),单独的这个类称为父类(基类或超类)。
可以理解为:“子类 is a 父类” - 类继承语法规则:
class Subclass extends SuperClass{ } - 作用:
继承的出现减少了代码冗余,提高了代码的复用性。
继承的出现,更有利于功能的扩展。
继承的出现让类与类之间产生了关系,提供了多态的前提。
注意:不要仅为了获取其他类中某个功能而去继承
3.多态
多态性,是面向对象中最重要的概念。
对象的多态性:父类的引用指向子类的对象 。可以直接应用在抽象类和接口上。
-
多态作用
提高了代码的通用性,常称作接口重用 -
前提
1.需要存在继承或者实现关系
2.有方法的重写 -
成员方法
编译时:要查看引用变量所声明的类中是否有所调用的方法。
运行时:调用实际new的对象所属的类中的重写方法。 -
成员变量
不具备多态性,只看引用变量所声明的类。 -
编译时类型和运行时类型
Java引用变量有两个类型: 编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。
若编译时类型和运行时类型不一致 , 就出现了对象的多态性 (Polymorphism)
多态情况下 :
“ 看左边 ” ,看的是父类的引用(父类中不具备子类特有的方法)
“ 看右边 ” ,看的是子类的对象(实际运行的是子类重写父类的方法)
注意:一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法。
举例:
Student m = new Student();
m.school = “pku”; // 合法,Student 类有school 成员变量
Person e = new Student();
e.school = “pku”; // 非法,Person 类没有school 成员变量
属性是在编译时确定的,编译时e 为Person 类型,没有school 成员变量,因而编译错误。
-
静态绑定和动态绑定(早绑定和晚绑定)
对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;
而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”
子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。
Person e = new Student();
e.getInfo(); // 调用Student 类的getInfo() 方法
编译时e 为Person 类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo() 方法,此即为动态绑定。 -
对象类型转换
1.基本数据类型的转换
自动类型转换:小的数据类型可以自动转换成大的数据类型
如long g=20; double d=12.0f
强制类型转换:可以把大的数据类型强制转换成小的数据类型
如 float f=(float)12.0; int a=(int)1200L
2.引用数据类型的转换
从子类到父类的类型转换可以自动进行
从父类到子类的类型转换必须通过造型( 强制类型转换) 实现
ps:
1)对Java 对象的强制类型转换称为造型
2)在造型前可以使用instanceof进行判断
3)无继承关系的引用类型间的转换是非法的
对象类型转换.png -
instanceof 操作符
x instanceof A :检验x 是否为类A 的对象,返回值为boolean 型。
注意:要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
举例:
public class Person extends Object {…}
public class Student extends Person {…}
public class Graduate extends Person {…}
public void method(Person e) {
if (e instanceof Person)
// 处理Person 类及其子类对象
if (e instanceof Student)
// 处理Student 类及其子类对象
if (e instanceof Graduate)
// 处理Graduate 类及其子类对象
}
