Java对象多态性的使用

来源:互联网 发布:民国时期期刊数据库 编辑:程序博客网 时间:2024/05/30 23:44

转载自:http://blog.csdn.net/aotumemedazhao1996/article/details/52818762

java接口可以实例化吗?


接口不可以实例化。但是接口对象可以指向它的实现类对象。
接口可以看做特殊的抽象类,只是所有的方法都是抽象方法(没有实现的方法),接口的方法都是默认public abstract的,
所以不能被实例化。
比如:

List Set Map都是接口
使用时先实现

List<String> list = new ArrayList<>();

有点类似于指针的感觉了。Factory接口可以用来代表实现它的类。比如:
public interface thing;
public class fruit implements thing;
thing something = new fruit();
这个something指的就是水果。

接口编程是为了实现多继承。

对象多态性在面向对象中是一个最重要的概念,在Java中主要有两种体现形式: 

1. 方法的重载和覆写 
2. 对象的多态性 
对于方法的重载和覆写在之前的讲解中,下面将重点介绍对象的的多态性。 
对象的多态性主要分为以下两种类型: 
(1) 向上转型:子类对象—》父类对象; 
(2) 向下转型:父类对象—》子类对象; 
对于向上转型,程序会自动完成,而对于向下转型时,必须明确的指明要转型的子类类型,格式如下:

对象向上转型:父类 父类对象 = 子类实例;对象向下转型:子类 子类对象 = (子类)父类对象;
  • 1
  • 2

下面进行对象向上转型的操作: 
【对象向上转型】

class A{    public void fun1(){        System.out.println("A-->public void fun1()");    }    public void fun2(){        this.fun1();    }}class B extends A{    //覆写A中的方法    public void fun1(){        System.out.println("B-->public void fun()1");    }    //子类中自己定义的方法    public void fun3(){        System.out.println("B-->oublic void fun3()");    }}public class PolDemo01{    public static void main(String[] args){        B b=new B();//定义子类实例化对象        A a=b;//发生了向上转型的关系,子类--》父类        a.fun1();//此方法被子类覆盖    }}
  • 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

程序运行结果:

B-->public void fun()1
  • 1

以上程序就是一个对象向上转型的关系,从程序的运算结果中可以发现,此时虽然使用父类对象调用fun1()方法,但是实际上调用的方法是被子类覆写过的方法,也就是说,如果对象发生了向上转型关系后,所调用的方法一定是被子类覆写过的方法。但是在此时一定要注意,此时的对象a是无法调用B类中的fun3()方法的,因为此方法只在子类中定义而没有在父类中定义,如果要想调用子类中的自己定义的方法,则肯定要使用子类实例,所以此时可以将对象进行向下转型。 
【对象向下转型】

class A{    public void fun1(){        System.out.println("A-->public void fun1()");    }    public void fun2(){        this.fun1();    }}class B extends A{    //覆写A中的方法    public void fun1(){        System.out.println("B-->public void fun()1");    }    //子类中自己定义的方法    public void fun3(){        System.out.println("B-->oublic void fun3()");    }}public class PolDemo01{    public static void main(String[] args){        A a=new B();//发生了向上转型关系,子类--》父类        B b=(B)a;//此时发生了向下转型关系        b.fun1();//调用方法被覆写的方法        b.fun2();//调用父类的方法        b.fun3();//调用子类定义的方法    }}
  • 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

运行结果:

B-->public void fun()1B-->public void fun()1B-->oublic void fun3()
  • 1
  • 2
  • 3

从以上程序中可以发现,如果要想调用子类自己的方法,则一定只能用子类的实例化对象,另外,在子类对象里调用从父类中继承过来的fun2()方法,fun2()方法要调用fun1()方法,由于此时fun1()方法已经被子类所覆写,所以此时调用的方法是被子类覆写过的方法。 

阶段性总结:

1. 向上转型主要特征,子类为父类对象实例化,父类接受子类对象功能,调用的方法一定是子类所覆写过的方法;(向上转型找共性

2. 向下转型主要特征,子类扩充了某些功能,这些功能父类没有定义,则需要执行向下转 型,以调用子类特有的功能;(向下转型找特性


对象向下转型的要求: 
在对象向下转型前,必须首先发生对象向上转型,否则将出现对象转化异常。 
了解了对象的多态性后,那么这个概念到底有什么用途哪?下面要求设计一个方法,要求此方法可以接收A类的任意子类对象,并调用方法,此时,如果不用对象的多态性,则肯定会使用以下形式的代码: 
【不使用对象多态性实现功能】
class A{    public void fun1(){        System.out.println("A-->public void fun1()");    }    public void fun2(){        this.fun1();    }}class B extends A{    //覆写A中的方法    public void fun1(){        System.out.println("B-->public void fun1()");    }    //子类中自己定义的方法    public void fun3(){        System.out.println("B-->poublic void fun3()");    }}class C extends A{    public void fun1(){        System.out.println("C-->public void fun1()");    }    public void fun5(){        System.out.println("C-->public void fun3()");    }}public class PolDemo04{    public static void main(String[] args){        fun(new B());//传递B类实例        fun(new C());//传递C类实例    }    public static void fun(B b){//接收B类实例        b.fun1();    }     public static void fun(C c){//接收C类实例        c.fun1();    }}
  • 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
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

运行结果:

B-->public void fun1()C-->public void fun1()
  • 1
  • 2

以上程序虽然实现了基本的要求,但是应该可以发现:如果按照以上的方式完成程序,则当产生一个A类的子类对象时,fun()方法就要被重载一次,则每一次扩充子类都必须修改类本身,这样肯定不方便,那么如果使用对象多态性完成可以很好地解决。 
【使用对象的多态性】

class A{    public void fun1(){        System.out.println("A-->public void fun1()");    }    public void fun2(){        this.fun1();    }}class B extends A{    //覆写A中的方法    public void fun1(){        System.out.println("B-->public void fun1()");    }    //子类中自己定义的方法    public void fun3(){        System.out.println("B-->poublic void fun3()");    }}class C extends A{    public void fun1(){        System.out.println("C-->public void fun1()");    }    public void fun5(){        System.out.println("C-->public void fun3()");    }}public class PolDemo04{    public static void main(String[] args){        fun(new B());//传递B类实例,产生向上转型        fun(new C());//传递C类实例,产生向上转型    }    public static void fun(A a){//接收父类对象        a.fun1();    }}
  • 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
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

运行结果:

B-->public void fun1()C-->public void fun1()
  • 1
  • 2

从上程序运行的结果发现,此时由于在fun()方法中使用了对象的多态性,所以可以接收任何的子类对象,这样无论子类如何增加,fun()方法都不用做任何的改变,因为一旦发生对象的向上转型关系之后,调用的方法一定是被子类覆写过的方法。

三、instanceof关键字

通过上面的分析发现,向下转型实际上比向上转型危险,因为有可能会造成错误,所以在Java中专门提供了一个instanceof的关键字,利用次关键字就可以判断出某一个对象是否是某一个类的实例

语法:

对象 instanceof  类   ——>返回boolean型数据

范例6:观察instanceof的使用

 

 

最规范的写法:

 

四、相互转型的意义

解释此类问题,假设Person类下有学生、工人、教师三个子类;人一定说话,那么每个身份的人说的话一定不同。要求定义一个方法,此方法可以接受Person类对象的所有引用(实现接受person类的所有子类对象);

 

 

 

 

实现方式一:利用方法的重载完成

实例7

 

上面的参数各写各的,没有统一

 

如果person类产生了100个子类,而且还有可能随时增加更多子类,最终要的是参数没有得到有效的统一,优化如下:

实现方式二:利用对象的向上转型操作完成

明确:对象在进行向上转型时可以自动完成父类接收子类对象的功能,同时转型之后所调用的的方法一定随实例化子类的不同,同一个方法一定执行不同的功能;


现在结果和之前完全一样,如果随意扩充子类的话,fun()方法不需要做任何修改可以满足所有功能;

 

六、总结

(一、)关于继承性和多态性总结

1. 这两个特性一定是相辅相成,缺一不可的

2. 继承性解决的是一个类功能扩充的问题,而多态性解决的是参数统一的问题,有了多态性之后才应该发觉,父类的设计是相当重要的,而且子类不要轻易的扩充父类里没有的方法,要按照父类已有的方法规格覆写方法;

(二、)关于对象转型问题

1. 向上转型(90%),自动完成,子类对象自动的转换为父类对象,而后调用的是子类所覆写过的方法;利用对象的向上转型可以解决参数参数统一问题;

2. 向下转型(1%),强制完成,不建议出现,当需要调用子类自己扩充的方法时使用

3. 不转型(9%),很多时候一些类是不进行转型操作的,例如String

六、多态性主要特征分为两类

1. 方法的多态性

1)重载:同一个方法名称,根据参数的类型或个数不同可执行不同的方法体;

2)覆写:同一个方法根据子类的不同,可以达到不同的功能

对象的多态性

1)向上转型:达到参数统一;

2)向下转型:调用子类的特殊功能

3. 利用instanceof关键字可以判断某一个对象是否是某一个类的实例



对于多态,可以总结以下几点:

一、使用父类类型的引用指向子类的对象;

二、该引用只能调用父类中定义的方法和变量;

三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用);

四、变量不能被重写(覆盖),"重写"的概念只针对方法,如果在子类中"重写"了父类中的变量,那么在编译时会报错。



原创粉丝点击