多态,抽象类,接口

来源:互联网 发布:程序员大牛 编辑:程序博客网 时间:2024/05/29 04:33

一.多态

1.概念:一个事物在不同时刻体现出的不同状态.

2.三个前提条件:

         a.必须有继承关系,没有继承关系,谈不上多态;

         b.必须有方法重写;

          子类出现了父类一样的方法声明.

         c.有父类引用指向子类对象:向上转型

                   Fuf = new Zi();

         多态的三个条件缺一不可;

3.多态的成员访问特点:

         a.成员变量:编译看左,运行看左;

         b.成员方法(非静态的成员方法):

                   编译看左,运行看右,由于存在方法重写,所以最终运行的是子类的成员方法.

         c.静态成员方法(静态方法算不上方法重写,静态直接跟类有关系!)

                   编译看左,运行看左;

         d.构造方法: 对对象进行初始化,由于是继承关系,所以还是分层初始化.

//父类

class Fu{

       publicintnum=10;

       //父类的成员方法

       publicvoid show() {

              System.out.println("show Fu..");

       }

       //静态方法

       publicstaticvoid function() {

              System.out.println("function Fu...");

       }

}

//子类

class Ziextends Fu{

       intnum = 20;

       publicvoid show() {

              System.out.println("show Zi");

       }

       publicstaticvoid function() {

              System.out.println("function Zi");

       }

}

//测试类

publicclass DuoTaiTest {

       publicstaticvoid main(String[]args) {

              //创建父类的对象:多态的形式

              //有父类引用指向子类对象:向上转型

              Fu f = new Zi();

              //访问成员变量

              System.out.println(f.num);

              //调用成员方法:show()

              f.show();

              //静态方法

              f.function();

       }

}

 

4.多态的好处(特点):

         a.提高代码的维护性(由继承保证)

         b.提高代码的扩展性(由多态保证)

java开发原则:高内聚,低耦合.

 

5.多态的弊端:

         不能访问子类特有的方法

解决方案:

         a.创建子类的具体对象,来访问自己的特有功能;虽然可以解决多态的弊端,但是从内存角度考虑,需要创建子类对象,那么必须在堆内存开辟空间,耗费内存,浪费空间!

         b.既然多态的第三个前提条件:父类引用指向子类对象,那么可不可以将子类的引用指向父类对象呢?

       可以的:向下转型:将父类的引用强制转换为子类的引用:前提必须有父类的引用存在;

       向下转型必须依赖于向上转型!            Zi z = (Zi) f;

 

class孔子爹{

       publicintage=40;

       publicvoid teach() {

              System.out.println("讲解JavaSE..");

       }

}

class孔子extends孔子爹{

       publicintage = 20;

       publicvoid teach() {

              System.out.println("讲解论语...");

       }

       //特有功能

       publicvoid playGame() {

              System.out.println("王者荣耀...");

       }

}

publicclass孔子装爹 {

       publicstaticvoid main(String[]args) {

              孔子爹k =new孔子();//向上转型:父类引用指向子类对象

              System.out.println(k.age);//成员变量:编译看左,运行看左

              k.teach();// 非静态成员方法:编译看左,运行看右

              孔子k = (孔子)k;//向下转型

              k.playGame();//访问子类的特有功能

       }

}

 

5.一般情况下:向下转型使用不当会造成一个异常:

                Throwable:

                                    error:严重问题

                                    Exception:

                                                       编译时期异常:

                                                     运行时期异常:RuntimeException

         运行时期异常:

                   类转换异常: ClassCastException

         ArrayIndexOutBoundException:数组角标越界异常;

         NullPointerException:空指针异常(解决方案:给对象做非空判断)

                   If(对象名=null){

         给该对象进行操作;

}

测试:看程序写结果

//看程序写结果

class A{

       publicvoid show() {

              show2();

       }

       publicvoid show2() {

              System.out.println("");

       }

}

class Bextends A{

       publicvoid show2() {

              System.out.println("");

       }

}

class Cextends B {

       publicvoid show() {

              super.show();

       }

       publicvoid show2() {

              System.out.println("");

       }

}

publicclass DuoTaiTest2 {

       publicstaticvoid main(String[]args) {

              A a = new B();

              a.show();

              B b = new C();

              b.show();

       }

}

         有继承关系:

                   分层初始化:父类先初始化,然后子类初始化

         多态的访问特点:

                 成员方法:(非静态的):编译看左,运行看右(方法重写)

二.抽象类

1.概念:

每一个动物的吃和睡的功能不一样,不应该把动物类定义为一个具体类,而是给出一个声明(abstract)

当一个类中如果有抽象功能(抽象方法)的时候,那么这个类一定要定义为抽象类!

abstract  class 类名{}

 

问题:一个抽象类中可以有非抽象方法吗?

                一个抽象类中可以抽象,也可以有非抽象的(作为一个判断题记忆!)

抽象类不能实例化:抽象类不能创建对象

       一个抽象类如何进行实例化:

                通过抽象类多态形式:父类的引用指向子类对象,通过子类进行初始化!

                抽象类的子类的特点:

                         1)抽象类的子类是抽象类,那么没有意义!

                               最终使用的就是通过子类进行对象初始化的,如果子类都被抽象修饰了,那么也不能创建对象,所以没意义

               

                 抽象类多态:

                                   强制子类必须重写当前抽象的父类中所有的抽象方法

                                    还可以提高代码的维护性(继承关系保证!)

Eg:

abstractclass Animal{

       //抽象方法:没有方法体的一个方法

       publicabstractvoid eat();

       publicabstractvoid sleep();

       //具体方法

       publicvoid show() {

              System.out.println("show Animal..");

       }

}

class Catextends Animal{

       @Override

       publicvoid eat() {

              System.out.println("猫吃鱼..");

       }

 

       @Override

       publicvoid sleep() {

              System.out.println("猫趴着睡觉..");

             

       }

}

//测试类

public class AbstractTest1 {

       publicstaticvoid main(String[]args) {

              Animal a = new Cat();//多态:父类引用指向子类对象

              a.show();

              a.eat();

              a.sleep();

       }

}

抽象类的成员特点

                         成员变量:

                                             可以是变量也可以是自定义常量

                         构造方法:

                                            抽象类可以有构造方法:包括有参构造和无参构造

                                            作用:通过抽象类多态的形式:让子类进行数据的初始化

                         成员方法:

                                            可以有抽象方法,也可以有非抽象方法

                                   

  抽象类的成员方法特性:

                         抽象方法:强制子类必须要做到一件事情:方法重写(覆盖)

                           非抽象方法:由继承保证可以去提高代码的复用性

abstractclass Fu2{

       private Stringname;

       privateintage;

       //成员变量

       publicintnum=100;

       publicfinalintnum2=200;//final修饰,自定义常量

       //无参构造

       public Fu2() {

             

       }

       //有参构造

       public Fu2(Stringname,intage) {

              this.name=name;

              this.age=age;

       }

       //抽象方法

       publicabstractvoid show();

       //非抽象方法

       publicvoid function() {

              System.out.println("function Fu2");

       }

}

//子类

class Zi2extends Fu2{

 

       publicvoid show() {

              System.out.println("show Zi2");

             

       }

      

}

//测试类

publicclass AbstractTest2{

       publicstaticvoid main(String[]args) {

              Fu2 f = new Zi2();

              f.show();

              f.function();

              System.out.println(f.num2);

       }

}

问题:

                一个类中如果没有抽象方法,那么这个类可不可以定义为一个抽象类呢?

                可以!为什么

                不能让其创建对象!

  

       abstract不能和哪些关键字共同使用?

                privateabstract不能共同使用

                finalabstract不能共同使用

                staticabstract不能共同使用

  

       实际开发中:public公共访问权限

三.接口

接口的概念:

  接口体现的是一种:扩展功能:           比如:猫可以跳高(并不是所有的猫都具有跳高功能)

       

        如何表示接口:

                            interface:接口                            interface 接口名{

 

                                                                                   }

                 接口里面的方法可以是非抽象方法吗?

                           不可以,只能是抽象方法

                 接口中不能有构造方法

                

                 接口的特点:不能实例化(不能直接创建对象)

                 接口如何实例化:

                           接口的子实现类:

                                    1)接口的子实现类是抽象类,没有意义,子类都不能创建对象了;实际开发中用的就是子类的对象进行初始化!

                                    2)接口的子实现类是非抽象类

                                             接口的实例化:就是通过子实现类对数据进行初始化!

               

  接口的子实现类和接口的关系:implements:

       格式:

                class子实现类名    implments(实现) 接口名{

  

                }

//定义跳高的接口

publicinterface Jump {

       //抽象方法

       publicabstractvoid jump();

       //接口中不能有非抽象方法和构造方法.

}

//子实现类

classCat2implements Jump{

       publicvoid jump() {

              System.out.println("猫可以调高了");

       }

}

//测试类

publicclass InterfaceTest1 {

       publicstaticvoid main(String[]args) {

              //接口对象:接口的引用指向子类对象

              Jump j = newCat2();

              j.jump();

       }

}

接口成员的特点:

                 成员变量:

                         只能是常量:存下默认修饰符:publicstatic final (永远建议自己给出默认修饰符)

                构造方法:

                         接口是没有构造方法的

                成员方法:

                         接口中的成员方法默认修饰符:publicabstract(永远建议自己给出默认修饰符)

 

 //定义一个接口

publicinterface Inter {

       //成员变量:只能是常量,存在默认修饰符public static final

       publicstaticfinalintnum1=10;

       publicstaticfinalintnum2=20;

       //成员方法:默认修饰符:public abstract

       publicabstractvoid show();

       publicabstractvoid function();

}

//定义接口的子实现类

publicclass InterImp1implements Inter {

 

       @Override

       publicvoid show() {

              System.out.println(num1);

              System.out.println(num2);

 

       }

 

       @Override

       publicvoid function() {

              System.out.println("function InterImp1..");

 

       }

 

}

//测试类

publicclass InterfaceTest2 {

       publicstaticvoid main(String[]args) {

              Inter i = new InterImp1();

              System.out.println(Inter.num1);//接口名.成员变量(当前变量被static修饰)

              System.out.println(Inter.num2);

              System.out.println("--------------------");

              i.show();

              i.function();

       }

}

类与类的关系:

                继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承!

类与接口的关系

                实现关系:implements,并且,一个类在继承另一个类的同时,可以实现多个接口

 (class 子实现类名  enxtends Object implements 接口名1,接口名2...)

接口与接口的关系

                继承关系:extends,可以支持单继承,也可以多继承!

interface Inter2{

        

}

interface Inter3{

        

}

 

//接口与接口的关系:extends

interface Zi extends Inter2{}

interface Son extends Inter2,Inter3{}

 

//子实现类

class InterImpl2  extends Object implements Inter2,Inter3{

        

}

public class InterfaceDemo3 {

 

}

面试题:

                 接口和抽象类的区别?

                

                 1)成员的区别:

                           成员变量:

                                    抽象类:成员变量可以是常量,也可以是变量

                                    接口:成员变量只能是一常量:存在默认修饰符:publicstatic final

                           构造方法:

                                    抽象类:可以有无参构造,有参构造方法

                                               作用:通过子类进行数据初始化(通过子类创建对象)

                                    接口:没有构造方法的

                           成员方法的区别:

                                    抽象类:可以有抽象方法,也可以有非抽象方法

                                    接口:只能是抽象方法:存在默认修饰符:publicabstract

                                   

                 2)关系的区别:

                           类与类的关系:

                                   继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承!

                                   类与接口的关系:

                                            实现关系:implements,并且,一个类在继承另一个类的同时,可以实现多个接口

                                             (class子实现类名  enxtends Object implements 接口名1,接口名2...)

                        

                                   接口与接口的关系

                                                     继承关系:extends,可以支持单继承,也可以多继承!

                                                    

                3)设计理念的区别:

                                   抽象类:

                                            体现的是一种"isa"的关系,存在继承关系!(抽象类多态)

                                   接口:

                                            体现的是一种"likea"的关系,由于接口的一种扩展功能

 

原创粉丝点击