javaSE(基础四) 面向对象(四)
多态
多态: 一种事物的多种形态|表现形式
多态的前提: 继承|实现
多态的最终体现: 父类的引用指向子类的对象
多态调用:
会调用子类中的重写方法
对子类新增不可见多态调用成员方法: 编译看父类|左边|类型,运行找子类|右边|对象
多态调用成员变量: 编译运行看父类|左边|类型多态引用调用时候,对子类新增成员不可见
多态前提下,想要调用子类的新增内容怎么办–>向下转型
转型:
基本数据类型类型转换 Cast
孔子装爹:
孔子爹类: class 孔子爹{void teach(){做生意…}}
孔子类 : class 孔子 extends 孔子爹{void teach(){讲论语…}; void play(){吃鸡…}}
一个人来找孔子爹去授课,但是不巧,孔子爹外出…,只有孔子在家
–多态
–向上转型: 从小到大 --> 自动类型提升
孔子决定化妆:装成孔子 爹的样子去授课
孔子爹 k = new 孔子();
k.teach(); //调用的是子类中重写的方法
–想要调用子类中独有的内容
–向下转型 : 强制类型转换 long l = 1; int i = (int)l;
孔子想和学生一起打游戏,但是孔子爹不会游戏,只能卸妆,变回孔子,才能使用孔子的能力打游戏
小范围类型 变量 = (小范围类型)大范围类型的数据;
孔子 kk = (孔子)k;
kk.play();
注意:
转型可能会遇到一种异常java.lang.ClassCastException 类型转换异常
运算符: instanceof
引用 instanceof 类型: 判断前面的引用指向的对象是否为后面类型的对象,或者前面的引用是否指向后面类型子类的对象,如果是返回true,不是返回false
编译:只检查前面的引用与后面的类型是否在一条继承体系上,如果在编译就不报错,不在编译就报错
//转型之前提前判断一下,防止类型转换异常
if(k instanceof KongZi){
//向下转型
KongZi zi = (KongZi)k;
zi.play();
}else if(k instanceof Brother){
Brother zi = (Brother)k;
zi.play();
}
//instanseof 右边是左边的父类或者本身,或者说其左边对象是否为其右边类的实例
KongZiDie k = new KongZi();
System.out.println(k instanceof KongZi); //true
System.out.println(k instanceof Brother); //false
System.out.println(k instanceof KongZiDie); //true
System.out.println(k instanceof Object); //true
System.out.println(k instanceof CC); //false
//System.out.println(k instanceof String); //false
多态习题
/*
* 做题四大原则:
* 一、继承链:自己没有找父
* A
* |
* B
* / \
* C D
* 二、 编译看类型、确定方法,运行找对象
*
* 三、就近最优原则
*
* 四、父类引用对子类新增方法不可见
*/
public class PolyTest {
public static void main(String[] args) {
//编译就能够确定方法表
A a1=new A(); //A_show(D) A_show(A)
//多态
A a2=new B(); //A_show(D) B_show(A)
B b =new B();
C c=new C();
D d =new D();
System.out.println(a1.show(b)); // A and A
System.out.println(a1.show(c)); // A and A
System.out.println(a1.show(d)); // A and D
System.out.println(a2.show(b)); // B and A
System.out.println(a2.show(c)); // B and A
System.out.println(a2.show(d)); // A and D
System.out.println(b.show(b)); // B and B
System.out.println(b.show(c)); // B and B
System.out.println(b.show(d)); // A and D
}
}
class A{
public String show(D obj){
return ("A and D");
}
public String show(A obj){
return ("A and A");
}
}
class B extends A{
//新增方法
public String show(B obj){
return ("B and B");
}
@Override
public String show(A obj){
return ("B and A");
}
}
class C extends B{
}
class D extends B{
}
抽象类
抽象: abstract
抽象方法: 被abstract修饰的方法就是抽象方法
没有方法体
必须存在与抽象类中
抽象类: 被abstract关键修饰的类就是抽象类
注意:
1.抽象类是不能实例化
2.抽象类中可以定义抽象方法,也可以定义具体方法,还可以定义任意内容
3.抽象类的使用:通过子类使用
1.具体的子类继承抽象类:重写里面所有的抽象方法+按需扩展
2.抽象子类: 按需重写抽象方法+按需新增
4.抽象方法: 必须被重写才能使用
5.抽象方法一旦被重写就不需要再次重写,但是可以根据需要进行重写
6.abstract关键字不能跟 private,final,static,native(本地)一起使用
接口
接口:
特殊的抽象类
一个引用数据类型
功能的集合
接口可以多实现,类只能单继承
解耦(耦合度: 联系)
定义开发规范
提高代码的复用性
注意:
1.定义类class 定义接口 interface
2.父类中定义子类的共性(属性,功能),接口中定义功能的集合
3.类继承父类 extends 类实现接口 implements
4.接口中内容的使用,通过接口的实现类取用
5.一个实现类需要先继承父类,后实现接口
6.类与类之间只能继承,接口与类之间只能实现,类去实现接口,接口与接口之间只能继承,可以多继承
7.接口能实例化么??? 不能
接口中的内容比较局限|特别:
jdk1.7及之前
1.公共的静态的常量
默认public static final修饰
2.公共的抽象的方法
public abstract 默认修饰符