面向对象----多态

1.认识多态

多态性是OOP中的一个重要特性,主要是用来实现动态联编的,换句话说,就是程序的最终状态只有在执行过程中才被决定而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性或扩展性。

多态可以让我们不用关心某个对象到底是什么具体类型。就可以使用该对象的某些方法,从而实现更加灵活的编程,提高系统的可扩展性

允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。

相同类域的不同对象,调用相同的方法,执行结果是不同的。

1.一个对象的实际类型是确定的

例如:new Student();    new Person();

2.可以指向对象的引用的类型有很多

一个对象的实现类型虽然是确定的,但是这个对象所属的类型可能有很多种。

例如:Student继承了Person类

1 Student s1 = new Student();
2 Person s2 = new Student();
3 Object s3 = new Student();

因为Person和Object都是Student的父类性

注:一个对象的实际类型是确定,但是可以指向这个对象的引用的类型,可以是这对象实际类型的任意父类型。

1.一个父类引用可以指向它的任何一个子类对象

1 Object c = new AnyClass();
2 Person p = null;
3 p = new Student();
4 p = new Teacher();
5 p = new Person();

2.多态中的方法调用

1 public class Person{
2   public void run(){}  
3 }
4 
5 public class Student extends Person{
6   public void run(){//重写run方法}
7 }

 

3.调用到的run方法,是Student从Person继承过来的run方法

1 main:
2 Person p =new Student();
3 p.run();  //调用到的run方法,是Student中重写的run方法

 

注:子类继承父类,调用a方法,如果a方法在子类中没有重写方法,那么就是调用的子类继承父类的a方法,如果重写了,那么调用的就是重写之后的方法。

子类中独有方法的调用

 1 public class Person{
 2   public void run(){}  
 3 }
 4 public class Student extends Person{
 5   public void test(){}  
 6 }
 7 
 8 main:
 9 Person p = new Student();
10 //调用到继承的run方法
11 p.run();
12 //编译错误,因为编译器检查变量p的类型是Person,但是在Person类中并没有发现test方法,所以编译报错
13 p.test();

 

注·:一个变量x调用方法test,编译器是否能让其编译通过,主要是看声明变量x的类型中有没有定义test方法,如果有则编译通过,如果没有则编译报错。而不是看x所指向的对象中有没有test方法。

原理:编译看左边,运行不一定看右边。

编译看左边的意思:java编译器在编译的时候会检测引用类型中含有指定的成员,如果没有就会报错。子类的成员是特有的,父类的没有的,所以他是找不到的。

子类引用和父类引用指向对象的区别

1 Student s  = new Student();
2 Person p = new Student();

 

但是变量p是父类型,p不仅可以指向Student对象,还可以指向Teacher类型对象等,但是变量s只能指Student类型对象,及Student子类型对象。变量p能指向对象的范围是比变量s大的。

Object类型的变量o,能指向所有对象,它的范围最大,但是使用变量o能调用到的方法也是最少的,只能调用到Object中的声明方法,因为变量o声明的类型就是Object.

注:java中的方法调用,是运行时动态和对象绑定的,不到运行的时候,是不知道到底哪个方法被调用的。

2.重写、重载和多态的关系

重载是编译时多态

调用重载方法,在编译期间就要确定调用的方法是谁,如果不能确定则编译报错。

重写是运行时多态

调用重写的方法,在运行期间才能确定这个方法到底是哪个对象中的,这个取决于调用方法的引用,在运行期间所指向的对象是谁,这个引用指向哪个对象那么调用的就是哪个对象中的方法。(java中的方法调用,是运行时动态和对象绑定的)

3.多态的注意事项

1.多态是方法的多态,属性没有多态性

2.编写程序时,如果想调用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。但是如果两个没有关联的类进行强制转换,会报:ClassCastException.比如:本来是狗,我把它转成猫。就会报这个异常。

3.多态的存在要有三个必要条件:要有继承,要有方法重写,父类引用指向子类对象

4.多态存在的条件

1.有继承关系

2.子类重写父类方法

3.父类引用指向子类对象

补充一下第二点,既然多态存在必须要有“子类重写父类方法”这一条件,那么一下三种类型的方法时没有办法表现出多态特性的(因为不能被重写):

1.static方法,因为被static修饰的方法时属于类的,而不是属于实例的

2.final方法,因为被final修饰的方法无法被子类重写

3.private方法和protected方法,前者是因为被private修饰的方法对子类不可见,后者是因为尽管被protected修饰的方法可以被子类见到,也可以被子类重写,但是它是无法被外部所引用的,一个不能被外部引用的方法,怎能谈多态呢?

5.方法绑定(method binding)

执行调用方法时,系统根据相关信息,能够执行内存地址中代表该方法的代码。分为静态绑定和动态绑定。

静态绑定:

在编译期完成,可以提高代码执行速度

动态绑定:

通过对象调用的方法,采用动态绑定机制。这虽然让我们编程灵活,但是降低了代码的执行速度。这也是java比c/c++速度慢的一个主要因素。java中处理final类,final方法,static方法,所有方法都是jvm在运行期才进行动态绑定的。

多态:如果编译时类型和运行时类型不一职,就会造成多态。

1212

posted @ 2020-09-21 22:53  罗晓峥  阅读(188)  评论(0)    收藏  举报