java的继承 inheritance

来源:互联网 发布:狸窝视频剪辑软件 编辑:程序博客网 时间:2024/05/29 13:18

1,为什么需要继承

        假设我们要写几个动物的类:
     小猫:眼睛,耳朵,尾巴,鼻子,爪子。。。。
     小狗:眼睛,耳朵,尾巴,鼻子,爪子。。。。
     小羊:眼睛,。。。。。。
     很显然,这些类中是有许多共同之处的,比如它们都有眼睛,耳朵,尾巴等,不同的只是各个成员(眼睛,尾巴等)的具体内容,如眼睛的大小,尾巴的颜色,长短等而已。如果每个类都单独来写,某些相同的代码就需要重复写许多遍,但怎样能解决这个问题呢?可不可以将具有相同功能的内容只写一次呢?这时,就需要用到继承(inheritance)。
     

2,继承的作用

     1,提高的代码的重用性;
     2,提高代码的可扩展性

3,继承的格式

    java中继承的关键字:extends
    格式:
          public class 类名(子类,派生类) extends 类名(父类,基类){
                          
          }
     注意:1,java中的继承是单继承,也就是说一个子类只能继承一个父类,但一个父类可以被多个子类所继承;
                2,子类可以继承到父类中的所有属性和方法,与访问修饰符无关。访问修饰符只能限制对象访问方法的范围。 
                3,子类可以定义父类中没有的属性和方法,但也只能由子类的对象进行调用。
                4,子类继承父类之后,实例化子类对象时,系统会首先实例化父类对象。
 举个例子:
package Extends;public class Student{       //父类 学生类public String name;public void study(){     //学习方法System.out.println("学生的名字是:"+name);}public void setName(String name){    //设置名字方法(参数)this.name = name;}public void eat(){System.out.println("学生每天都在食堂吃饭");}public void rest(){System.out.println("学生每天都在宿舍休息 ");}}
package Extends;public class UNStudent extends Student{//子类  大学生类public static void main(String[] args) {// TODO Auto-generated method stubUNStudent uns = new UNStudent();uns.setName("张三");uns.study();uns.cet6();}public void cet6(){     //子类特有的方法System.out.println("大学生不想考六级!!!");}}

4,自动转型

        1),自动转型的条件是什么?
                        必须存在继承关系。

     2),自动转型的格式:
                        一,将子类对象的类型定义成父类对象的类型,也就是说,子类对象的类型可以自动转型成父类对象类型。
                             父类名  对象名  = new 子类构造方法(参数值,...);
              
Student un = new UNStudent();
                         注意:1,子类类型转成父类类型后不能调用子类特有的方法;
                                    2,方法重写时,先调用子类还是父类的方法,取决于new关键字之后的类。
                                         
                        二,访问修饰符  返回值类型 方法名(父类名  参数名,...){

               }
               子类名  对象名  = new 子类构造方法(参数值,...);
               方法名(对象名)

      3),自动转型会引发什么问题?
                无法调用子类特有的属性和方法。
                原因:java编译和运行机制的不同
                           java编译时,编译的是文件,是根据对象名的类型进行编译的。如果对象名调用的属性和方法在对象名的类型中存在,就会通过编译,否则不通过;
                          而运行时,会使用对象名中存储的对象的堆内存首地址。调用方法时,会根据对象名中存入的首地址优先进行调用,如果对象名中没有才会去调用父类的。
 

5,强制转型

   1),强制转型的条件是什么?
                        1,必须存在继承关系
                        2,之前实例化的对象是子类的对象(也就是说,如果一个对象可以被强制转型,那么它肯定在前面某个地方被自动转型过)

   2),强制转型的格式:
                        子类名  子类对象名 =(子类名)父类对象名;

例子:
Student stu = new UNStudent();     //将子类对象定义为父类类型(自动转型)stu.setName("李四");stu.study();//对象stu不能调用子类特有的方法cet6UNStudent stu2 = (UNStudent)stu;     //将父类类型的对象stu强制转换成子类类型(强制转型)stu2.cet6();

6,方法重写 override

     1),什么时候需要方法重写:
              当父类中存在一个方法,子类中也有这个方法,但子类中方法的具体实现与父类中不同时,重写该方法。

     2),方法重写的条件:
              1,必须存在继承关系;
              2,子类方法的访问修饰符必须大于或等于父类方法的访问修饰符;
              3,子类方法的返回值类型,方法名以及参数都必须与父类一致;
              4,方法的实现不能相同。
package Extends;public class JUStudent extends Student{//子类 中学生类public void study(){    //方法的重写System.out.println(name + "是中学生");}public static void main(String[] args){JUStudent jus = new JUStudent();jus.setName("王五");jus.study();Student stu3 = new JUStudent();stu3.setName("赵六");stu3.study();}}
注意:在子类重写父类的某方法后,最后调用时调用的是子类的方法。这种情况下,如果一定要调用父类中的成员函数,可以使用super关键字。调用方法是:super.函数名

举个例子:
父类:
package Jicheng;public class Dialog_01 {protected String title;public Dialog_01(String title){this.title = title;}public void show(){System.out.println(title+"对话框显示");}    }
子类:
//子类package Jicheng;public class FrontDialog extends Dialog{private String frontName;public FrontDialog(String title,String frontName){  this.title = title;this.frontName = frontName;}public static void main(String[] args) {// TODO Auto-generated method stubFrontDialog fd = new FrontDialog("字体","宋体");}}
此时,子类public FrontDialog(String title,String frontName)处会报错。因为只要实例化子类对象,系统就会自动先实例化一个父类对象与之对应,当然此时调用的是父类没有参数的构造函数。
解决方法:
1),给父类增加一个无参的构造函数
//解决方法1:给父类增加一个没有参数的构造方法package Jicheng;public class Dialog_01 {protected String title;public Dialog_01(){}public Dialog_01(String title){this.title = title;}public void show(){System.out.println(title+"对话框显示");}    }
2)在子类的构造函数中,第一句用super给父类的构造函数传参数
//解决方法2:在子类的构造方法中,第一句用super()给父类构造函数传参数package Jicheng;public class FrontDialog_02 extends Dialog{private String frontName;public FrontDialog_02(String title,String frontName){ super(title); this.frontName = frontName;}public static void main(String[] args) {// TODO Auto-generated method stubFrontDialog_02 fd = new FrontDialog_02("字体","宋体");}}
注意:用super给父类传参时,必须写在子类构造函数的第一句,且传入的参数必须和父类构造函数中参数列表类型相匹配。

7,接口

     1),为什么需要接口?
           一般情况下,父类都比子类更加抽象,因为父类中的属性和方法比子类更少,而且父类的方法中,我们只能笼统的描述,而不能像子类方法一样更为具体。
           所以当我们只知道父类的对象应该做什么,但不知道该怎样做时,我们就可以定义这样的一个类,类中的方法只有方法的定义,没有方法体,这个类我们就叫它接口。

     2),定义接口的格式;
            public interface 接口名  extends 接口,... {

//定义常量
public static final 数据类型  常量名  = 值;

//定义抽象方法
public abstract 返回值类型  方法名(数据类型 参数名,...);

}
注意:
1.接口只有一个访问修饰符public。
2.接口默认会提供public、static、final、abstract关键字。
3.接口不能实例化对象。
package Extends;//定义一个接口(一种数据类型),主要用来扩展子类//**只有方法体,但没有对方法的定义**public interface Person {    //接口的属性默认为public static final(公共的静态常量)public static final int num = 1000;void eat();    //接口中的方法默认为public abstract(公共的抽象方法)public abstract void rest();}
    
    3),实现接口:
           实现(继承)接口的关键字:implements
格式:
public class 类名  extends  类名   implements 接口,... {
//注意:类必须要实现(重写)接口中所有的抽象方法。(包含接口继承父接口中的抽象方法)

}

            一个类可以继承多个接口。
package Extends;public class Student implements Person{       public static void main(String[] args){     //实现person接口Person per = new Student();     per.eat();per.rest();}}

8,抽象类

     1),什么是抽象类:
           父类中如果规定一个抽象函数:abstract 函数名() ,其必须被重写。含有抽象函数的类就是抽象类,也必须用abstract修饰。
   
     注意:1,抽象类不能被实例化;
                2,抽象函数必须被重写,除非子类也是抽象类;
                3,抽象类中也可以含有普通成员函数。

9,final关键字

    1,用final修饰一个类:
                   表示该类不能被继承
    2,用final修饰一个函数:
                   表示该类在被子类继承的情况下,该函数不能被重写
    3,用final修饰一个成员变量:
                   表示该成员变量的值不许改变,也就是说,不允许重新赋值。因此,一般用final关键字定义一个常量。

                  



     








0 0