一多态:某一事物在某一时刻表现出来的多种形态。父类的引用指向了他的某个子类的对象。
1、多态的前提
1).一定要有继承关系的
2).有方法重写
3).父类引用指向了子类的对象
2、多态成员的访问特点:--》》父类应用不能访问子类特有的成员(变量、方法)
1).普通的成员变量
A):只能访问父类中定义成员变量;若是父类没有定义时,则就是编译错误。。(无覆盖)
B):若发生覆盖时,父类引用指向了子类的对象,访问的是父类的成员变量。
编译看左边:编译时父类必须有此成员,否则报错
执行看左边:执行时,打印的结果看左边的引用类型。
2).普通的成员方法
A:未发生重写时,访问父类的方法。
B:发生重写,访问子类的方法。
编译看左边:编译时,父类需要有此方法,否则编译错误。
运行看右边:运行时,看引用的指向对象,运行的是子类中的方法。
方法空间
A:多个对象时,每个对象都有独立的成员变量空间。但“方法空间”只有一个,多个对象共享一个“方法空间”。
B:多个对象调用“同一方法“时,会使用动态绑定。哪一个对象调用方法,其调用的属性就是实例化对象的类中的属性。而调用方法的引用是一个地址值,是所调用的方法所在类实例化对象的堆内存地址值。
3).静态的成员方法
静态的成员都是和类有关系的,跟对象无关的,没有动态绑定的。
编译看左边:编译时,父类要有此类方法,否则编译出错的;若是父类没有此方法,则父类不能访问。
执行看右边:运行时,运行还是父类的方法。
看静态方法和一般的成员方法是有区别的,所有说 静态的方法重写不能算是真正的方法重写。
3、总结:多态时,属性和静态的方法的调用看引用,成员方法调用看对象!!!
多态发生时,父类的引用指向子类的对象,可以理解为,基本数据类型的默认提升!!!!
二、面试题:
1、复杂的子父类调用情况
class Fu
{
public void show()
{
System.out.println("fu show");
}
}
class Zi extends Fu
{
public void show()
{
System.out.println("zi show");
}
public void method()
{
System.out.println("zi method");
}
}
class Test
{
public static void main(String[] args)
{
Fu f = new Zi();
f.method();
}
}
此题运行错误,是因为父类引用访问不到子类特有的方法。
2、子父类的方法调用关系
class A
{
public void show()
{
show2();
}
public void show2()
{
System.out.println("我");
}
}
class B extends A
{
public void show2()
{
System.out.println("爱");
}
}
class C extends B
{
public void show()
{
super.show();
}
public void show2()
{
System.out.println("你");
}
}
public class Test
{
public static void main(String[] args)
{
A a = new B();
a.show(); //父类的引用指向子类对象,会首先调用父类的未被复写的方法show(),其中有show2()方法,由于show2()方法被子类重写,访问子类的方法
B b = new C();
b.show(); //B类型的引用指向了C子类的对象,首先调用父类B的show()方法,此时B类中”隐含着“一个show()方法,
//方法中有show2()方法,由于show2()方法被子类C重写,所以调用子类的show2方法。
}
}
输出的是”爱 你“
三、多态的好处
1、提高了程序的维护性,由继承保证---》》在方法声明上,形式参数为引用型变量的时候传递的是引用也就是内存地址值。其形参变量,可以接受任何子类类型的引用,因为多态,因为形参是父类类型的。
2、提高了程序的扩展性,由多态保证
四、多态中的类型转换--》》用来访问子类特有的功能
1、向上转型:父类的引用指向了子类的对象,隐式自动转换
特点:A:多态;B:访问的是父类中定义的成员,子类特有的不可以访问。
2、向下转型:如果确定父类引用指向了某个子类对象,那么可以将这个父类类型的引用强制转换为该子类类型的引用。必须是所对应的子类类型引用,其他的类不可以。
3、案例:
class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}
以及
Animal p0 = new Animal();
Dog p1 = new Dog ();
Cat p2 = new Cat ();
Animal p3 = new Dog ();
Animal p4 = new Cat ();
p0 = p1; //可以的,理解为Animal p0=new Dog();
p1 = p2; //不可以,相互没有继承关系
p1 = (Dog)p3; //可以啊,强制类型转化
p2 = (Cat)p4; //强制类型转换
4、instanceof关键字---》》用于向下转型时 判断所用
1)、这是一个双目运算符
2)、格式:父类类型变量 indtanceof 某类类型;if(a instanceof B){
System.out.println("a 指向的是 B的对象,可以安全向下转换为B类型");
B b2 = (B)a;}
3)、他会返回一布尔类型的值,如果是子父类关系,返回值为true
4)、用于向下转换之前进行判断
五、抽象类
(一)抽象类概述
1.父类中的方法被所有子类重写
2.抽象方法,可以只有方法声明,而没有方法体,使用关键字 abstracet
3.如果父类中有一个方法是“抽象方法”,那么该类必须也是抽象类 Abastracet class
4.如果是抽象类,那么该类就不能被实例化了,不能有该类对象了
5.一个抽象类,就是用来做父类的,被其他类来继承
(二)、抽象类的特点
1.抽象类和抽象方法,用关键字abstract修饰。格式:abstract class 类名;public abstract void 方法名
2.抽象类中和抽象方法中可以什么都不定义。但是有抽象方法必须是抽象类。
3.抽象类中可以有什么?
A:成员变量(包括静态)
B:成员方法(包括静态方法)
C:构造方法也可以有,子类在实例化对象的时候会调用父类的无参或者有参的构造方法
D:抽象方法,可以只有方法声明,但是没有方法体。
4.子类可以继承一个抽象类,仍旧是单继承
5.子类继承一个抽象类,那么必须要▲全部▲重写父类的抽象方法。如果重写一部分或者重写不完全,那么子类也必须是抽象的
(三)、抽象类总结
1.抽象类是不可以被实例化的,但是可以在多态中通过子类实例化
2.子类继承抽象类,必须重写全部抽象方法。若不能全部重写,那么子类必须也是抽象的。
3.一个抽象类可以继承自一个抽象类
4.一个类中有抽象方法那么这个类也必须是抽象类,而一个抽象类中可以没有抽象方法。
(四)、抽象类中成员的特点
1.成员变量:可以是变量也可以是常量
2.成员方法:抽象方法和非抽象方法
抽象方法:用于限定子类必须完成某些动作
非抽象方法:用于提高代码的复用性
3.构造方法:必须有构造方法,可以是无参也可以是有参数的,但是类本身不能被实例化。用来实例化子类对象时初始化父类的数据。
(五)抽象类的小问题
1、一个抽象类中没有抽象方法,可以吗?如果可以有什么意义?
可以的,一个抽象类可以没有抽象方法,但是一个抽象方法必须在一个抽象类中。可以用来作为一个父类来被人继承,且能防止本类被实例化。
A:可以有成员变量和成员方法被子类继承提高代码的复用性
B:而抽象的方法可以被重写,对子类一种约束
2、abstract不能和那些关键字共存?
A:abstract方法是抽象方法,用来被子类重写的,所以不能和private、final共存
B:abstract的方法第一个抽星方法,是可以没有方法体的,不能分配内存空间,但是static是一个静态的方法,在没有创建对象的时候就会分配内存空间。
六、接口interface
(一)接口的概述
》》如果一个抽象类中的★方法都是抽象★方法时,就可以定义为接口。★
★★1.当一个抽象类中没有用来实现功能的方法,只有抽象方法
★★2.接口和抽象类一样不可以被”实例化“,所以用来做父类
3.子类是”实现接口“,使用关键字implantment
4.如果一个子类实现某一个接口 ,那么必须★全部重写★接口中所有的抽象方法。否则这个类必须是抽象类。
5.接口中可以定义什么?
★★A:接口可以定义成员变量》》★只能是全局常量★,声明为public static final
★★B:成员方法》》★只能是抽象方法★,且必须声明为public abstract,可以不用声明,但是编译器会隐式的自动添加。为什么?因为接口就是用来扩展功能的,
C:构造方法???
★★6.接口中的方法都是抽象方法,可以只有方法声明,而没有方法体
(二)接口的特点
1、使用关键字,interface;格式:interface 接口名
2、子类实现接口,关键字 :class 类名 implements 接口名
3、接口本身是个抽象的感念,不能实例化,可以在多态中,通过具体的子类实例化。
4、一个子类可以实现多个接口,必须重写所有接口中的抽象方法。格式:class 类名 implements A,B,C{}
5、一个接口可以继承自另一个接口或者多个接口,可以多继承
6、一个抽象类可以实现接口,可以实现多个接口,而且可以不重写全部或者不全部重写接口中的方法。
7、一个类可以同时继承自一个父类,并且实现一个或者多个接口,要先继承后实现。
(三)类、抽象类、接口的关系
1、一个类可以继承自一个类,但必须是单继承。
2、一个类可以继承自一个抽象类,也是单继承。
3、一个类可以实现多个接口,多实现
4、一个抽象类可以继承自一个抽象类,单继承,并且实现多个接口。
5、一个接口可以继承多个接口,多继承。
(四)抽象类和接口的区别
相同点:都不能被实例化
区别:1、第一的关键字不同
2、子类使用时,接口要实现,抽象类要被继承
3、内部成员:
接口:成员变量,加上 public static
抽象类:成员变量
成员方法、构造方法、抽象方法