多态:
可以理解为事物存在的多种体现形态。
多态体现:
父类的引用指向了自己的子类对象。
父类的引用也可以接收自己的子类对象。
多态的前提:
必须是类与类之间有关系,要么继承,要么实现。
通常还有一个前提:存在覆盖。
多态的好处:
多态的出现大大的提高程序的扩展性。
多态的弊端:
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5.多态中成员的特点:
父类引用不能调用子类对象特有的数据。
如果想要调用子类多想的特有方法时,如何操作?
强制将父类的引用,转成子类类型。
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化。
多态的向上转型和向下转型例子如下:
abstract class Person2{
public abstract void sleep();
}
class Student2 extends Person2{
public void sleep(){
System.out.println("zZzZ!");
}
public void playGame(){
System.out.println("DNF");
}
}
class Student3 extends Person2{
public void sleep(){
System.out.println("good sleep!");
}
public void smoking(){
System.out.println("smoking!");
}
}
public class duotaiDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//Person2 p = new Student2();//向上转型,父类的引用型变量p指向了自己的子类对象,并且父类有sleep()的方法,子类也有,不过子类覆盖了父类的sleep()方法,那么运行的就是子类自己的sleep();
//p.sleep();
//Student2 t = (Student2)p;//向下转型,强制将父类的引用转换成了子类对象,子类就就可以调用自己特有的playGame()方法了。父类没有playGame()方法。
//t.playGame();
method(new Student2());//将一个对象作为参数传递了。
//method(new Student3());
}
public static void method(Person2 p3){//这个method方法接收了一个对象,那么就可以写成这样:Person p3 = new Studnet2();这里做了一个动作,向上转型了,Student2转换成了Person2.
p3.sleep();
if(p3 instanceof Student2){//对传入的对象进行一个判断,以免出现类型转换异常。p3引用用instancof来测试它所指向的对象是否是Student2类的一个实例。
Student2 s2 = (Student2)p3;
s2.playGame();
}
else if(p3 instanceof Student3){
Student3 s3 = (Student3)p3;
s3.smoking();
}
}
}
在多态中非静态成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
{个人理解:就是向上转型的时候,父类引用子类对象,在编译的时候先要查看父类中是否有调用的方法,然后再运行时期就要查阅子类中是否也有和父类一样的方法,并且覆盖了。运行后那就是覆盖后的结果。当想要调用子类自己特有的方法的时候,父类没有的,那就得向下转型,那才能调用子类特有的方法。}
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类。)
在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。
{综合理解:多态中,静态成员函数静态方法区中,而在静态方法区中只有类名的引用,就相当于类名点方法。一调用这个方法就绑定了这个方法的所属的类了。而非静态区中有this引用和super引用。如果当fu f = new zi()此时这个父类的引用f指向了子类对象,那么调用方法的是时候f.method()方法的时候就相当于new zi().method()。所以运行是的子类对象的方法。}
接口引用型变量指向自己的子类对象。这也是多态的表现!
interface MachineSlot{
public void commectTV();
public void runGame();
}
class GameMachine{
public void Machine(){
System.out.println("Machine run");
}
public void UseMachineSlot(MachineSlot m){//这里就相当于是 MachineSlot m = new GameCard();接口类型指向了自己的子类对象
if(m!=null){
m.commectTV();
m.runGame();
}
}
}
class GameCard implements MachineSlot{
public void runGame(){
System.out.println("DNF Run");
}
@Override
public void commectTV() {
// TODO Auto-generated method stub
System.out.println("电视连接成功");
}
}
public class DuotaiCase {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
GameMachine gm = new GameMachine();
gm.Machine();
gm.UseMachineSlot(null);
gm.UseMachineSlot(new GameCard());
}
}
|