Java基础之继承和多态

                    继承部分

继承:将多个类抽像为一个独立的类,让独立的类和多个类产生继承关系

继承 的关键字:extends

 格式:

 class子类名 extends 父类名{

                                   ...

                         }

 继承的好处:

                1)提供了代码复用性,解决了代码的臃肿

                2)它是多态的前提(多态的前提是必须有继承关系)

 继承的特点:

        1>子类继承父类,是继承了父类所有的东西(成员变量,成员方法,包括私有),但是子类不能使用私有的东西,只能通过父类的公共的访问间接的让子类访问它.

        2>在Java中,继承只支持单继承,不支持多继承(子类名 extends 父类名1,父类名2,...)

       但是,Java是可以支持多层继承...

 这里注意:           

         类和类之间的关系:继承关系

         类和接口之间的关系:实现关系

 继承中的注意事项:

                           1)构造方法不能被继承,但是通过super关键字去访问

                         2)私有的可以间接的去访问

                         3)什么时候使用extends?

  继承体现的是一种"is a"的关系:

         如果A是B的一种或者B是A的一种,这个可以使用继承!

不要随意的使用继承,只要有"is a"的关系就使用它.

     假设:有一个A类

                           class A{

                                            publicvoid show1(){}

                                            publicvoid show2(){}

                           }

  

                有一个B类

                         classB{

                                            publicvoid show1(){}

                                            publicvoid method(){}

                         }

   按照正常的情况:发现A类和B类中有共同的show1()方法,根据继承的概念,---->让B类继承A类

                           class B extends A{

                                            publicvoid method(){}

                         }

  

  没有问题,但是继承了A类,show1(),show2()也继承过来了,可能show2()并不是我想要的功能;对于这种情况不要使用继承

 

 这里我们强调一下 Java开发设计原则:低耦合,高内聚

       耦合:类和类之间的关系 ,尽量降低耦合性

        内聚:指的是做一件事情能力(尽量使用一个类完成的事情不要多个类去完成..)

 

 在继承中,成员变量的名称问题

       1.当前子类继承父类的时候,子类和父类中的成员变量名称不一致的情况,分别输出就可以了;

        2.当子类和父类中的成员变量名称一致的情况:

                         1)先到子类的局部位置找,如果找到了,就输出

                         2)没有找到,到子类的成员位置找,有就输出,

                         3)在类的成员位置还没有找到,直接父类的成员位置找,有就输出

                           4)如果还没有,就保存了,不存在这个变量

继承中成员方法的问题

                1.子类继承父类,访问成员方法名不一致的情况,分别调用!

                2.当子类中的成员方名和父类中的成员方法名一致的情况:

                         1)现在子类的成员位置找,如果有就调用

                         2)如果没有找到,在父类的成员位置找,有就调用

关于继承的用法:

                父类中被private修饰的,是可以继承,但是只能间接的去访问私有的..

                父类被private修饰 成员属性,子类不不能直接访问的

               

  子类不能继承父类的构造方法,但是可以通过super

 

Java提供了关键字:super:代表的父类的空间标识(父类的引用或父类的对象)

 

 this和super关键字的用法:

                         成员变量:

                                   this:

                                                     this.成员变量; (访问当前类)

                                   super:

                                                     super.成员变量;(访问父类)

                                           

                         构造方法:

                                   this();///访问当前类的无参构造

                                   this("");//访问当前类的有参构造

                                   super()://访问的父类的无参构造

                                   super("")://访问的是父类的有参构造..

                         成员方法:

                                   this.xx()

                                   super.xx()

关于继承的成员的问题

                         构造方法:

                                   子类继承父类,都会默认的访问父类的无参构造方法

                                   为什么呢?

                                    假设数据还没有被初始化完毕,所以应该先让父类进行初始化,然后在让子类初始化--->分层初始化

代码说明

package cn.itcast_011;

 

classFu2{

   publicFu2(){

      System.out.println("父类无参构造方法....");

   }

  

   publicFu2(Stringname){

      System.out.println("父类的有参构造方法...");

   }

}

//子类

classZi2extendsFu2{

   publicZi2(){

//    super() ;

      System.out.println("子类的无参构造....");

   }

  

   publicZi2(Stringname){

//    super() ;

      System.out.println("子类的有参构造....");

   }

}

 

//测试类

publicclassExtendsDemo{

 

   publicstaticvoidmain(String[]args){

     

      Zi2zi=newZi2();

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

      Zi2zi2=newZi2("高圆圆");

     

   }

}

 

  思考:

              如果父类的无参构造没有提供?怎么办?

肯定报错;

             如何解决:

                      1)可以将父类的无参构造提供出来

                      2)可以super关键字去访问父类的带参构造...

代码说明

package cn.itcast_011;

 

classFather2{

  

   publicFather2(Stringname){

      System.out.println("父类的有参构造....");

   }

}

//子类继承父类

classSon2extendsFather2{

   publicSon2(){

      super("随便给");// //访问父类的有参构造

      System.out.println("子类的无参构造...");

   }

 

}

publicclassExtendsDemo{

  

   publicstaticvoidmain(String[]args){

      Son2s=newSon2();

   }

}

结果:

父类的有参构造....

子类的无参构造...
          3)还可以在子类中通过this(),访问本类中的有参构造,间接的去访问父类带参构造

 

代码说明:

package cn.itcast_011;

 

classFather2{

  

   publicFather2(Stringname){

      System.out.println("父类的有参构造....");

   }

}

//子类继承父类

classSon2extendsFather2{

   publicSon2(){

 

      super("随便给");

      System.out.println("子类的无参构造...");

   }

  

   publicSon2(Stringname){

      this();

      System.out.println("子类的有参构造..");

   }

}

 

publicclassExtendsDemo{

  

   publicstaticvoidmain(String[]args){

      Son2s=newSon2();

   }

}

结果:

父类的有参构造....

子类的无参构造...

            子类的构造方法必须有一个(有参构造/无参构造),让父类进行初始化!

看程序写结果:

         提示:     子类继续父类,父类先进行初始化,然后子类进行初始化,这就是继承中分层初始化

package org.westos.继承_01;

class X {

         Yb = new Y();

         X(){

                   System.out.print("X");//x

         }

}

 

class Y {

         Y(){

                   System.out.print("Y");  //y

         }

}

 

public class Z extends X {

         Yy = new Y();

         Z(){

                   System.out.print("Z");

                  

         }

         publicstatic void main(String[] args) {

                   newZ();

         }

}

 

结果:YXYZ

 

 

 

                    Final

方法重写:由于子类继承父类的时候,提供一摸一样的方法声明,然后会将父类该方法覆盖掉

面试题:

方法重写与方法重载的相同点:

    1)方法的名称相同

    2)都可以用于抽象方法和非抽象方法之间。

方法重写与方法重载的不同点:

    1)方法重写要求参数必须相同,而方法的重载要求参数必须不同。

    2)方法重写要求返回类型必须相同,而方法重载对此没有限制。

    3)方法重写只能用于子类重写父类的方法,而方法的重载用于同一个类的所有方法(包括从父类中继承的方法)

    4)父类的一个方法只能被子类重写一次,而一个方法在所在的类中可以被多次重载。

Finna的引入:有时候(具体的需求),不需要子类重写父类的功能,针对这种情况,Java提供了一个关键字:final 最终的,终态的,不能修改的意思

final不仅可以修饰基本数据类型,还可以引用类型

                   如果final修饰的是一个基本数据类型:基本数据类型的值不能再改变了...

                   如果final修饰的是一个引用类型数据:引用类型的地址值不能再改变了,但是堆内存中的成员变量的值可以变得

final的初始化时机:

                 1)被final只能被赋值一次(final int a = 10)                    final int a ;

                   //在使用之前进行初始化,赋值(在构造方法之前赋值) (非静态的...)

作用:

         它可以修饰类,那么该类不能继承

        它可以修饰成员方法,成员方法不能被重写

        它可以修饰变量,此时这个变量是一个常量

 

       常量的分类:

                字面值常量:

                         字符串常量,字符常量,,,,

 

                自定义常量(final修饰的)

                         pubic final int num = 100;

这里插入一个有趣的看程序写结果题:

解题关键:继承:继承父类中所有的东西,除过构造方法

                继承的初始化:分层初始化

              

package org.westos.多态;

class A {

         publicvoid show() {

                   show2();

         }

         publicvoid show2() {

                   System.out.println("我");

         }

}

class B extends A {

        

         /**

          *解决问题的关键

          * public void show(){

          *   show2() ;

          * }

          */此处从父类继承下来的show()

 

         publicvoid show2() {

                   System.out.println("爱"); //爱

         }

}

class C extends B {

         publicvoid show() {

                   super.show();

         }

         publicvoid show2() {

                   System.out.println("你");// 你

         }

}

 

public class DuoTaiTest {

         publicstatic void main(String[] args) {

                   Aa = new B();

                   a.show();         

                   Bb = new C();

                   b.show();

         }

}  
结果:爱你

                                                                   多态部分

多态:在同一个时刻,体现出来的不同状态;

       水:           固态                   气态                   液态

 多态的前提:

                1)必须有继承关系

                         子类继承父类,存在一些特点

                2)必须有方法重写

                         子类继承父类,方法重写的目的

                   3)就是必须有父类的引用指向子类对象      (向上转型)

                                   父类名  fu = new  子类名() ;

                通过父类对象的创建是通过子类在堆内存新建了了一个对象,由于子类又继承了父类,父类的引用(初始化)是通过子类新建对象进行的..

  多态中的成员访问特点:

                1)成员变量:                       编译看左,运行看左...

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

                3)构造方法:构造方法(无论子类,还是父类),都是对对象进行初始化

                4)静态成员方法:        编译看左,运行看左(静态跟类有关系,算不上方法重写)

多态的好处:

                 可以提供代码的复用性:继承保证

                可以提高的代码的扩展性:由多态保证...  (父类的引用指向子类对象)

多态的弊端:

                         父类引用指向子类对象,不能访问子类特有功能

                  Father3 f = new Son3() ;   父类的引用指向子类对象 (向上转型)

 可不可以将子类的引用指父类的引用呢?         (向下转型)

                 可以,将父类的引用强制转换子类的引用

举例说明:

package org.westos.多态;

class Father3{

        

         publicvoid show() {

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

         }

}

class Son3 extends Father3{

         publicvoid show() {

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

         }

         //子类的特有关功能

         publicvoid method() {

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

         }

}

public class DuoTaiDemo4 {

public static void main(String[] args) {

                   Father3f  = new Son3() ;//向上转型

                   f.show();

                   Son3s = (Son3) f ; //前提是必须有父类的引用

                   //将父类的引用强制转换子类的引用  ,向下转型使用不当,会出现一个异常:属于运行时期异常:ClassCastException

                   s.method();

         }

}

 

 


 

 

 

阅读更多

没有更多推荐了,返回首页