多态[Java]


多态:事物的多种形态。即:
不同的对象收到相同的消息,产生不同的结果。
相同的对象收到不同的消息,产生不同的结果。

比如:
张三收到一部手机,会打游戏
李四收到一部手机,会发微信
王五收到一部手机,会听歌曲
赵六收到一部手机,会看电影
即,不同的人收到相同的手机,产生不同的玩法,就是不同的对象收到相同的消息,产生不同的结果。
因此说,手机这个事物具有多种形态,叫多态。

比如:
张三接到领导的电话,电话里说,小张……….
张三接到老婆的电话,电话里说,老公……….
张三接到父母的电话,电话里说,儿子……….
张三接到朋友的电话,电话里说,哥们……….
即,相同的人收到不用的消息,产生不同的称呼,就是相同的对象收到不同的消息,产生不同的结果。
因此说,张三这个人具有多种形态,叫多态。

多态如何用代码一步步实现的:

  1. 提高代码的复用性和扩展性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Animal{
void sing(){
System.out.println("唱歌");
}
class Cat extends Animal{
void sing(){
System.out.println("喵喵的唱歌");
}
}
class Dog extends Animal{
void sing(){
System.out.println("汪汪的唱歌");
}
}
public class duotai{
public static void main(String[] args){
Cat c1=new Cat();
c1.sing();
Cat c2=new Cat();
c2.sing();
Cat c3=new Cat();
c3.sing();

Dog d1=new Dog();
d1.sing();
Dog d2=new Dog();
d2.sing();
Dog d3=new class Animal{
void sing(){
System.out.println("唱歌");
}
class Cat extends Animal{
void sing(){
System.out.println("喵喵的唱歌");
}
}
class Dog extends Animal{
void sing(){
System.out.println("汪汪的唱歌");
}
}
public class duotai{
public static void main(String[] args){
Cat c1=new Cat();
c1.sing();
Cat c2=new Cat();
c2.sing();
Cat c3=new Cat();
c3.sing();

Dog d1=new Dog();
d1.sing();
Dog d2=new Dog();
d2.sing();
Dog d3=new Dog();
d3.sing();
}
}

我们可以看到,每new出一个对象,就需要去调用方法,很麻烦,我们可以写一个函数,进行传参,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class duotai{
public static void main(String[] args){
Cat c1=new Cat();
Cat c2=new Cat();
Cat c3=new Cat();
function(c1);
function(c2);
function(c3);
Dog d1=new Dog();
Dog d2=new Dog();
Dog d3=new Dog();
function(d1);
function(d2);
function(d3);
public static void function(Cat mao){//形参是Cat类型的变量
mao.sing();}

public static void function(Dog gou){public class duotai{
public static void main(String[] args){
Cat c1=new Cat();
Cat c2=new Cat();
Cat c3=new Cat();
function(c1);
function(c2);
function(c3);
Dog d1=new Dog();
Dog d2=new Dog();
Dog d3=new Dog();
function(d1);
function(d2);
function(d3);
public static void function(Cat mao){//形参是Cat类型的变量
mao.sing();}

public static void function(Dog gou){//形参是Dog类型的变量
gou.sing();}
}
  1. 多态:上面虽然提高了代码的复用性,但还是麻烦,因为每new一个类对象,就需要写一个函数,因此可以这样写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class mlx{
public static void main(String[] args){
Cat c1=new Cat();
Cat c2=new Cat();
Cat c3=new Cat();
function(c1);
function(c2);
function(c3);

Dog d1=new Dog();
Dog d2=new Dog();
Dog d3=new Dog();
function(d1);
function(d2);
function(d3);
}
static void function(Animal a){
a.sing();
}

//形参可以是Animal类型的变量,因为Cat和Dog都继承自它,
//等同于Animal a=new Cat() Animal a=new Dog() 向上转型,
public class mlx{
public static void main(String[] args){
Cat c1=new Cat();
Cat c2=new Cat();
Cat c3=new Cat();
function(c1);
function(c2);
function(c3);

Dog d1=new Dog();
Dog d2=new Dog();
Dog d3=new Dog();
function(d1);
function(d2);
function(d3);
}
static void function(Animal a){
a.sing();
}

//形参可以是Animal类型的变量,因为Cat和Dog都继承自它,
//等同于Animal a=new Cat() Animal a=new Dog() 向上转型,
//这就是多态。
}
  • 多态的好处:不仅可以提高代码的复用性,还可以提高代码的可扩展性。

  • 多态的体现:父类引用指向子类对象,即向上转型了。

多态成员变量的特点(原理):

  1. 编译时,参阅的是引用型变量所属的类中是否有调用的方法;

  2. 运行时,参阅的是对象所属类中是否有调用的方法;

    意思是,编译时是向上转型,看父类中是否有调用的方法,运行时,是看传进来的对象有没有方法可以重写。


多态的使用

多态的前提:

  1. 类与类之间必须存在关系,可以是继承关系,也可以是实现关系;
  2. 父类中一定要有sing()方法,因为向上转型,只能访问父类的方法,如果父类中没有该方法,就报错了;
  3. 必须要有重写,否则多态没有意义更不能实现多态了,因为正常向上转型后只能访问父类成员,
    如果方法没有重写,就输出“唱歌”了,有重写才能输出自己的sing()方法,喵喵或旺旺的唱;
  4. 多态=向上转型+重写;

多态的弊端:

  • 只能用父类的引用,访问到父类的成员,再看是否有重写;

最后说明:主函数中如果定义方法,一定要设置static静态,我们知道当建立这篇java文档时,主函数类就已经存在了,因此在主函数中的写的方法要加静态,静态是伴随着类的存在而存在,如果不加,这个方法就访问不到了,必须让方法和主函数一起存在。

1
2
3
static void functionstatic void function(Animal a){
a.sing();
}
  1. 多态中的向下转型:

  2. 如下,因为多态只能看到父类成员,所以如果子类成员中有非重写的方法,就访问不到了,可以使用向下转型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Dog extends Animal{
void sing(){
System.out.println("汪汪的唱歌");
}
void fangfa(){
System.out.println("多管闲事");
}
}
public class duotai{
public static void main(String[] args){
Dog d1=new Dog();
function(d1);
}
static void function(Animal a){
a.sing();
Dog d=(Dog)a;class Dog extends Animal{
void sing(){
System.out.println("汪汪的唱歌");
}
void fangfa(){
System.out.println("多管闲事");
}
}
public class duotai{
public static void main(String[] args){
Dog d1=new Dog();
function(d1);
}
static void function(Animal a){
a.sing();
Dog d=(Dog)a;//向下转型
d.fangfa();
}
}

提示:如果不是特殊需要,也没必要在多态中向下转型访问非重写方法,在上面d1.fangfa(),单独调用就ok了,可操性也很大。因为在多态中向下转型反而要和重写方法一起输出,如果不想一起输出就麻烦了,况且如果只需要访问非重写方法,更没必要使用多态了,向上又向下来回转型,反而麻烦了。