我们知道,面向对象有三大特征:封装、继承、多态
其中封装和继承比较好理解,我们重点来谈一谈多态,首先简单回顾一下封装和继承
1.封装
封装简单来说就是数据的隐藏;
封装的步骤:
1.使用private修饰需要封装的成员变量;
2.提供一个公开的方法设置或访问私有的属性;
例如: set属性名(…); //设置属性名
get属性名();//访问属性
封装的意义:
- 隐藏代码的具体实现细节;
- 统一用户的调用接口;
- 提高系统的可维护性;
2.继承
- 继承是类与类之间的一种关系,子类(派生类)继承父类(基类);
- 类和类之间只能是单继承,接口可以多继承;
- 父类中的属性和方法可以被继承,子类也可以重新定义或追加属性和方法等;若父类属性和方法用private修饰,在子类继承中就不可直接使用;
- 父类中的构造器是不能被子类继承的,但子类的构造器会隐式调用父类无参构造器;
3.多态
什么是多态?父类引用指向子类对象,可以表现出不同的表现形式和形态;
多态的必要条件:
- 继承:必须存在继承关系;
- 重写:子类对父类中某些方法进行重写,在调用这些方法时就会调用子类的方法。
- 向上转型:父类引用指向子类对象,这样该引用既能调用父类的方法,又能调用子类的方法;
多态情况下注意:
- 一个对象的引用类型可以是该对象类型的任意父类型;
- 父类和子类存在同名成员变量,无论静态或非静态,默认访问父类中的;
- 父类和子类存在同名的非静态方法,默认访问的是子类的非静态方法;
- 父类和子类存在同名的静态方法,默认访问的是父类的静态方法;
- 不能访问子类特有的属性和方法;
总结:只有同名非静态方法访问的才是子类的;
多态中方法的调用:
public class Person{
public void run(){
}
}
public class Student extends Person{
}
//调用到的run方法,是Student从Person继承过来的run方法
main:
Person p = new Student();
p.run();
public class Person{
public void run(){}
}
public class Student extends Person{
public void run(){
//重写run方法
}
}
//调用到的run方法,是Student中重写的run方法
main:
Person p = new Student();
p.run();
注意:子类继承父类,调用fun方法,如果fun方法在子类中没有重写,就调用子类继承父类的fun方法;
如果重写了,那么调用重写之后的方法;
来看下一个例子,如果是调用子类中独有的方法:
public class Person{
public void run(){
}
}
public class Student extends Person{
public void test(){
}
}
main:
Person p = new Student();
//编译报错,因为编译器检查变量p的类型是Person,但是在Person中没有发现test方法,所以编译报错.
p.test();
原理:编译看左边,运行不一定看右边;
编译看左边的意思:java 编译器在编译的时候会检测引用类型中是否含有指定的成员,如果没有就会报错。test是子类特有的方法,所以他在父类中找不到就会报错;
如果要调子类test方法用则需要向下转型,需要把变量的类型进行转换;
Person p = new Student();
Student s = (Student)p;
s.test();
或者
//注意这种形式前面必须要两个小括号
((Student)p).go();
引用数据类型之间的转换必须是父与子的关系,为了避免上述错误的发生,每次强转之前,应该使用instanceof进行判断,格式如下:
if(引用变量名x instanceof 目标类型y)
出结果是true还是false,主要是看变量x所指向的对象实际类型是不是Y类型的"子类型";
判断引用变量指向的对象是否为目标类型;
子类引用和父类引用指向对象的区别
//例如:Student类 继承 Person类
Student a = new Student();
Person b = new Student();
变量a只能调用Student独有的方法,包括继承来的方法;
变量b只能调用Person中有的方法,包括继承来的方法;
java中的方法调用,是运行时动态和对象绑定的,不到运行的时候,是不知道到底哪个方法被调用的;
重载是编译时多态;重写是运行时多态;
以下三种类型方法不能表现出多态(因为不能重写)
- static方法,因为被static修饰的方法属于类,而不属于实例(可以被子类继承,但不能重写);
- final修饰的方法
- private和protected修饰的方法
private修饰的方法对子类不可见
protected修饰的方法可以被子类重写,但无法被外部引用