黑马程序员——Java基础知识——面向对象(二)

来源:互联网 发布:美萍软件介绍 编辑:程序博客网 时间:2024/06/04 23:32

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!

 一、继承

       什么是继承:

        面向对象的一个重要特征,在以后的操作中会经常使用。当多个类中存在相同属性或行为时,将这些相同的内容抽取到单独一个类中,那么多个类无需再定义这  些属性和行为,只要继承这个类即可。那个单独的类称之为父类,其他的类就是子类。例如工人和学生都可以向上抽取出人这个父类,在父类中定义姓名、年龄等属  性,然后通过继承,工人和学生也具备了这种属性。在代码中通过extends表示继承关系。当类与类之间有了继承的关系,子类可以直接访问父类中的非私有的属性  和行为。继  承的出现提高了代码的复用性。让类和类之间产生了关系,有了这个关系,提供了多态的前提。在Java语言中,只支持单继承,不支持多继承,但Java  中有另一种体现  方式,叫多实现,在以后会学习到。注意,当类与类之间有所属关系时才可以继承。这种所属关系称为is a.

      如何使用继承:

            Java中可以多层继承,就是建立一个继承体系,如同爷爷、父亲和孩子的关系,例如:

            class A{}

           class B extendsA{}

            class C extendsB{}

        当要使用一个继承体系中所具备的功能时,要先查体系中父类的描述,因为父类中定义的是该体系中的共性功能。通过了解共性功能,就可以知道该体系中的  基本功能。这样这个体系就可以基本使用了;而在具体调用时,要创建最子类的对象,因为父类可能无法创建对象,而子类对象中又有更多的功能,除了基本功能外  还有其特有的。总结为一句话就是:查阅父类功能,创建子类对象使用功能。

 例如:

class Person{   //在父类中定义都共同具有的姓名、年龄属性以及睡觉的方法。   String name;   int age;   public void sleep(){ System.out.println("sleep");}}class Worker extends Person{  //因为继承父类,也具备父类的属性以及睡觉的方法,并定义工人特有的方法   public void work(){ System.out.println("work");}}class Student extends Person{  //因为继承父类,也具备的属性以及睡觉的方法,并定义学生特有的方法   public void study(){ System.out.println("study");}}

   3.继承中成员的特点

     (1)成员变量:如果子类中出现非私有的同名成员变量时,子类访问本类中的变量,用this,访问父类中的同名变量,则要用super。super和this都存在于方法  区中,使用方法相似。this表示本类的引用,super表示父类的引用。

     (2)成员方法:当子类和父类有一模一样的方法时,当子类对象调用该方法,会运行子类方法的内容,如同父类的方法被覆盖,这种情况称为:重写(覆盖)。

 当子类继承父类,沿袭了父类的方法,在子类中方法的内容却与父类不同,这时就可以用到重写,保留父类的方法定义,重写方法内容。子类的方法中同时具有父类

 方法中的内容时,可以用super.方法。例如:

class Person{     public void sleep(){ System.out.println("sleep");     }}class Worker extends Person{  //复写父类方法   public void  sleep(){   System.out.println(" earlier to sleep");   }}class Student extends Person{  //复写父类方法,并调用父类方法。   public void sleep(){       super.sleep();       System.out.println("第二天早起读书");   }}
     要注意几点:子类要覆盖父类,必须保证子类权限大于或等于父类权限,才可以覆盖,否则编译失败;静态只能覆盖静态;父类中的私有方法不能被重写。

      (3)构造函数

        在对子类对象进行初始化时,父类的构造函数也会运行,因为子类的每一个构造函数默认的第一行都有一条隐式的super()。通过super()语句,会访问父类中空  参数的构造函数。子类对象在初始化时一定要访问父类中的构造函数,是因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这  些数据进行初始化的。所以子类在对象初始化时,要先访问父类中的构造函数。如果要访问父类中非空参数的构造函数,需要通过定义super语句来指定,同this语句  一样,super语句也必须定义在构造函数中的第一行。子类的构造函数第一行也可以定义this语句来访问本类中的构造函数。总之,子类中至少会有一个构造函数访问  父类中的构造函数。

  final关键字

        final(最终),作为一个修饰符。具有以下特点:

        1、可以修饰类、函数、变量。

        2、被final修饰的类不可以被继承。这样就可以避免被继承、被子类复写功能。

        3、被final修饰的方法不可以被覆盖。

        4、被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。

       当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过_连接。

        5、内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。

 

 二、抽象类

           多个类中出现相同功能,但功能具体内容不同,那么在抽取过程中,只抽取了功能定义,并没抽取功能主体,那么只有功能声明,没有功能主体的方位称为抽  象方法。抽象方法没有方法主体,方法的具体实现由该类的子类去完成。包含抽象方法的类叫做抽象类。例如:

abstract class Person{//定义表示睡觉的抽象方法public abstract void sleep();}class Worker extends Person{//工人睡觉的具体方法public void sleep(){    System.out.println("早睡");}}class Student extends Person{//学生睡觉的具体方法public void sleep(){    System.out.println("晚睡");}}
        从上面的代码可以看出,抽象类和抽象方法都必须用abstract修饰。抽象方法定义在抽象类中,但同时抽象类中也可以有非抽象方法,抽象方法没有方法主体,只  有方法声明。抽象类不可以被创建对象,因为调 用抽象方法没有意义。抽象类中的抽象方法要被使用,必须由子类覆盖抽象类中的所有抽象方法,然后建立子类对象  调用,否则子类还是抽象类。

       抽象类与一般类相比,没有太大的不同,都是描述事物,只不过该事物中出现了一些不知道具体内容的方法部分。这些不确定的部分,也是该事物的功  能,需要明确出来,但是无法定义主体。通过抽象方法表示;抽象类比一般类多了一个或多个抽象函数,并且不可以被实例化;抽象类虽然不能创建对  象,但是也有构造函数,供子类实例化调用。

         注意的是,抽象类中也可以没有抽象函数,这样做是为了不让建立该类的对象。在使用abstract关键字修饰方法和类时,不能同时使用private、final、  static进行修饰。因为final修饰的类不能被继承,而抽象类是一个父类;private修饰的方法不能被复写,而抽象方法必须被复写;static修饰的方法,不需要  对象调用,而抽象方法运行没有意义。

          下面就通过一段代码,说明抽象类的使用。如下:

  

/**需求:开发一个系统时需要对员工进行建模,员工包含3个属性:姓名、工号以及工资。      经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。请使用继承的思      想设计出员工类和经理类。员工类:name id pay经理类:继承了员工,并有自己特有的bonus。*///定义员工类,定义所有公司成员的共同属性和方法class Employee{//定义共同的姓名、工号、工资的属性private String name;private String id;private double pay;Employee(String name,String id,double pay){this.name = name;this.id = id;this.pay = pay;}//定义工作的抽象方法,工作内容由员工根据工作范围自己去实现。public abstract void work();}class Manager extends Employee{    //定义经理类特有的奖金属性private int bonus;Manager(String name,String id,double pay,int bonus){   super(name,id,pay);this.bonus = bonus;}//经理的具体工作内容public void work(){System.out.println("manager work");}}class Pro extends Employee{Pro(String name,String id,double pay){super(name,id,pay);}//普通员工的具体工作内容public void work(){System.out.println("pro work");}}
      模板方法:在定义功能时,功能的一部分是确定,但是有一部分是不确定的,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去。由该类的 的子类去完成。如果不确定的方法没有默认的方法主体,就用抽象方法表示,然后由子类去复写。例如:

/**需求:获取一段程序运行的时间。原理:获取程序开始和结束的时间并相减即可。*/abstract class GetTime{   public final void getTime(){//表示程序开始时的时间long start = System.currentTimeMillis();runProgram();//表示程序结束时的时间long end = System.currentTimeMillis();System.out.println("毫秒:"+(end-start));}//具体程序未知,用抽象方法表示public abstract void runProgram();}class SubTime extends GetTime{    //定义具体的运行程序 public void runProgram(){        for(int x=0; x<3000; x++){System.out.print(x);}}}
  

 三、接口
       
可以理解为一个特殊的抽象类,但接口中的方法都是抽象的。当一个类中所有的方法都是抽象时就可以用接口来表示,接口用interface关键字来表示,而子类与接口通过implements(实现)产生关系,并必须覆盖其所有抽象方法,才能创建子类对象,否则该类是个抽象类。接口中常见的定义是常量和抽象方法。两者都有固定的修饰符,常量:public static final ;方法:public abstract;也可以在常量和方法前不写这些修饰符,编译时会自动添加,但为了提高阅读性,一般时候都加上。下面通过一段简单的代码,了解一下接口及其子类的格式,如下:

//定义一个类表示男子的接口interface Man{//定义性别属性,常量用大写字母表示public static final String SEX="man";//定义表示工作的抽象方法public abstract void work();}//定义一个类表示年轻男子,实现Man接口class YoungMan implements Man{  //覆盖接口中的抽象方法  public void work()  {    System.out.println("工作时间长");  }}
        接口是对外暴露的规则,接口的出现降低了耦合性,能对程序的功能进行扩展;类与接口是实现关系,java支持多实现,一个类可以继承一个类的同时 实现多个接口; 而接口和接口之间是继承关系。在使用接口时要注意,子类需覆盖接口中的所有抽象方法,否则子类还是个抽象类;当一个类实现多个接口时,多个接口中不能有返回值类型不同的同名抽象函数,这样子类无法实现复写。
        接口与抽象类都是由下向上抽取出来的。但两者又有很多区别:抽象类体检继承关系,父类与子类是"is a"的关系,一个类只能继承一个抽象类,而接口体现实现关系,接口与子类是"like a"关系,一个类可以实现多个接口;抽象类中可以定义非抽象方法,子类可以直接使用,类中可以定义私有变量和方法。而接口中所有的方法都是抽象的,并且所有成员都有固定的修饰符,所有成员的权限都是公有的;下面看一个接口与抽象类都有应用的程序,例如:

//定义一个抽象类,表示人  abstract class Person  {         //定义抽象的饮食方法      abstract void eat();      //定义共同的睡觉方法      void sleep()      {          System.out.println("sleep");      }  }    //定义一个接口,表示训练 interface Training{      public abstract void train();  }    //定义表示运动员的Athlete类,继承Person类,实现训练接口  class Athlete extends Person implements Training  {      //复写饮食方法      void eat()      {          System.out.println("多吃牛肉");      }        //复写训练方法      public void train()      {          System.out.println("每天都要训练");      }  }    //定义表示学生的Student的类,不训练class Student extends Person {         //复写饮食方法      void eat()      {          System.out.println("多吃蔬菜");      }  }      


  -------------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

0 0