1 多态
- 概念:事物的多种状态
对象的多态性:
一个对象可以使用不同的类型来表示,一个对象可以使用不同类型的引用来接收
类型的多态性:
一个类型可以使用不同的子类对象实现,一个类型的引用可以接收不同的子类对象 - 实现多态的前提:
(1)两个类之间需要有子父类的继承关系(接口和实现类之间的实现关系)
(2)必须使用父类的引用接收子类的对象(接口的引用接收实现类的对象) - 目的:
为了方法的重写, 提高代码的扩展性
1.1 多态中访问成员变量的特点
- 特点:
编译看左边(父类),运行看左边(父类) - 说明:
(1)多态的对象名,访问一个变量,在编译的时候,先看=左边类型中有没有该变量的 定义,如果有编译成功,可以使用。
(2)运行的时候,看=左边类型中该边浪如何赋值,父类中如何赋值,就如何使用
代码
package demos1;
public class Demo02 {
public static void main(String[] args) {
Animal a = new Cat();
//编译看父类,有定义,可以使用
//运行看父类:动物类
System.out.println(a.name);
//运行看父类:3
System.out.println(a.age);
//编译报错:编译看父类,父类中没有定义不能使用
// System.out.println(a.color);
}
}
1.2 多态中访问成员方法的特点
- 特点:
编译看左边(父类),运行看右边(子类) - 说明:
(1)编译的时候看=左边的父 类中,有没有该方法的定义,如果有就可以使用
(2)运行的时候看=右边的子类中,该方法如何实现的,子类如何实现就如何执行
代码
package demos1_poly.demo1;
public class Demo03 {
public static void main(String[] args) {
//多态定义:父类引用指向子类对象
Animal a = new Cat();
//编译看父类,有定义可以使用
//运行看子类:子类如何实现,就如何使用
a.print();
a.eat();
//编译失败:父类中没有定义,不能使用
// a.catchMouse();
}
}
1.3 多态中访问静态方法的特点
- 特点:
编译看左边(父类),运行看左边(父类) - 注意:
多态中访问静态方法,父类的引用调用,就执行父类中定义的实现内容
静态方法可以被子类继承,但是不能被子类重写
1.4 超人案例
1.4.1 向上向下转型
- 向上转型:
使用父类的引用接收(指向)子类的对象
特点:
不管是访问属性还是访问方法,都需要编译看父类
如果属性和方法在父类中有定义,才可以使用,没有定义不能使用
缺点:降低了对象的访问范围 - 向下转型:
将指向子类对象的父类引用,恢复为子类的引用
子类类型 子类对象 = (子类类型)对象名;
特点:恢复了子类对象访问范围 - 总结:
(1)如果接收子类对象的引用是父类类型,该引用的访问范围和super关键字相同, 指向子类对象中的父类对象。
(2)如果使用指向子类对象的父类引用访问方法,根据动态绑定机制,去子类中寻找 该方法的实现方式。
(3)向下转型之后,虽然两个变量中存储的是同一个地址,引用访问的范围和this一样,根据就近原则访问数据。
代码
package demos1_poly.demo2;
public class Demo01 {
public static void main(String[] args) {
//向上转型
//只能访问父类中定义的内容
Man m = new SuperMan();
System.out.println(m.name);//Mike
m.talkBunisess();
// m.fly(); 因为多态变量表示,只能使用父类定义的,不能使用子类特有的
//向下转型
//恢复了对象本身的访问范围
SuperMan sman = (SuperMan)m;
//可以访问子类特殊的方法
sman.fly();
System.out.println(sman.name);
}
}
class Man{
String name = "Mike";
public void talkBunisess(){
System.out.println("谈一个几个亿的小生意!!!");
}
}
class SuperMan extends Man{
String name = "superMan";
@Override
public void talkBunisess(){
System.out.println("谈一个几千亿的大生意!!!");
}
public void fly(){
System.out.println("飞着去救人");
}
}
1.5 instanceof关键字
- 格式:
引用 instanceof 类型 - 特点:
判断左边的引用是否是属于右边的类型对象
如果是结果为真,如果不是结果为假 - 作用:
在向下转型的时候,先判断该引用是否属于某一个类型,如果属于,就强转,否则不强转
代码
package demos1_poly.demo3;
public class Demo {
public static void main(String[] args) {
useAnimal(new Cat());
useAnimal(new Dog());
}
public static void useAnimal(Animal a){// Animal a = new Dog() Cat c = new Dog()
a.show();
//判断a引用是否属于毛猫类
//属于猫类,结果为真
if(a instanceof Cat){
//将引用转为向下转为猫类
//执行猫类的特殊方法
Cat c = (Cat)a;
c.catchMouse();
}
//判断a引用是否属于狗类
//属于猫狗类,结果为真
if(a instanceof Dog){
//将引用向下转为狗类
//执行狗类的方法
Dog d = (Dog)a;
d.lookHouse();
}
}
}
1.6 多态的好处
package demos1_poly.demo4;
public class Demo {
public static void main(String[] args) {
JuiceMachine jm = new JuiceMachine();
jm.makeJuice(new Apple());
jm.makeJuice(new Orange());
jm.makeJuice(new WaterMelan());
}
}
class JuiceMachine{
//在方法的形参列表中,定义一个父类的类型引用
//将来可以传递任何子类的对象(多态接收)
//将来可以根据传递的子类对象,执行子类方法的实现内容
public void makeJuice(Fruit f){//Fruit f = new Apple(); Fruit f = new Orange();
f.flow();
}
}
class Fruit{
public void flow(){
}
}
class Apple extends Fruit{
public void flow(){
System.out.println("流出苹果汁");
}
}
class Orange extends Fruit{
public void flow(){
System.out.println("流出橘子汁");
}
}
class WaterMelan extends Fruit{
public void flow(){
System.out.println("流出西瓜汁");
}
}
2 抽象类
2.1 抽象方法
- 概念:将每一个子类中方法的相同部分进行一个提取,只有声明相同,只定义方法的声 明,没有实现内容。只有声明没有实现内容的方法就是一个抽象方法。
- 为了表示该方法是一个抽象方法,使用一个关键字:abstract 修饰方法
- 抽象方法不能在普通类中定义,只能在抽象类中定义,只能将类型也通过关键字abstract 修饰
2.2 抽象类特点
- 抽象类使用关键字:abstract修饰
- 抽象类和抽象方法的关系:
抽象方法只能在抽象类中定义
抽象类中可以没有抽象方法 - 抽象类不能实例化(不能创建对象)
- 抽象类的子类有不同的两条分支:
如果子类继承抽象类之后,重写了父类的每一个抽象方法,那么子类就是一个普通类
如果子类继承抽象类之后,没有重写完父类中的抽象方法,子类只能定义为一个抽象类 - 即使类型变为一个抽象类,要使用该类型,也需要先编译为一个字节码文件后运行
2.3 抽象类成员特点
- 抽象类可以定义变量(属性),不能被抽象
- 抽象类中可以定义普通的成员方法,也可以定义抽象的方法
- 抽象类中需要定义构造方法吗?
需要。
一个类型是否需要定义构造方法,跟当前类是否可以创建对象无关。
跟当前类是否可以定义属性有关,如果类中可以定义属性,就需要对属性初始化,就需 要定义构造方法。
2.4模板设计模式
- 可以将每一个子类中都相同的内容,提取到父类中定义,将每一个子类中不同的内容, 可以在父类中定义为抽象方法,用于让子类强制重写。
- 效果:相同的代码没有反复定义多次,而且每一个子类也有自己不同的内容执行
模板类代码
package demos2_abstract.demo3;
public abstract class HomeWork {
public void Q1(){
System.out.println("1、喜羊羊与灰太狼中,灰太狼的老婆叫什么?");
System.out.println("A:红太狼 B:粉太郎 C:粉红太狼");
System.out.println(Answer1());
}
public void Q2(){
System.out.println("2、天龙八部中乔峰的大招叫什么?");
System.out.println("A:葵花点穴手 B:打狗棒法 C:降龙十八掌");
System.out.println(Answer2());
}
public abstract String Answer1();
public abstract String Answer2();
}
子类代码
package demos2_abstract.demo3;
public class Stu1 extends HomeWork{
@Override
public String Answer1() {
return "A";
}
@Override
public String Answer2() {
return "C";
}
}