java 语言程度设计 李元朝 第8章 接口和包

从安全性和效率角度考虑,java只允许类的单重继承,但借助于接口,可以实现多重继承。接口是一组常量和抽象方法的集合,抽象方法只声明方法头, 而没有方法体。

包用来组织类和接口,是一组相关类和接口的集合。包提供了类的访问和保护管理机制

8.1 抽象类和方法

             抽象类是抽象了子类共同的行为,声明与实现区别,提供了方法声明与方法实现相分离的机制,使基类表现出共同的行为模式,不同子类表现出多态性

             1.声明抽象方法

               [修饰符] abstract 返回值类型 方法名(参数表)

               说明:1抽象方法声明不需绘画出方法头,不需要方法体,以;结束。

                       2.构造方法不能声为抽象类。

              计算图形面积的抽象方法area()可采用如下的声明:

               public abstract area();

  2.声明抽象类

              [权限修饰符] abstract class 类名

            {

                   成员变量;

                      abstract 方法名( ); //定义抽象方法

                }

                  说明:类体中包含抽象就方法的类必须声明为抽象类。

                              抽象类不能实例化。

                              抽象类子类只有给出每个抽象方法的方法体,即覆盖每个抽象方法后,才能创建子类对象

    例8-1 利用抽象类表示多类图书。

                         

                 image

                            8-1 各类图书的属性和行为

                 考虑到了科技书、文艺书和教材都属于图书范畴,都有相同的行为,可以使用抽象类声明他们共同的成员变量和抽象方法。

abstract class Book {

    int  bookPage;                     //图书页码
      float  discount;                    //图书折扣
      double  price;                     //图书价格
      public Book(int bookPage,float discount)
       {
        this.bookPage=bookPage;
        this.discount=discount;
       }   
      abstract  void  show_kind();            //显示图书种类
      abstract  double  getPrice(int bookPage,float discount);    //计算价格
      public void show_price()       //显示价格
      {
         System.out.println("This book's price is "+price);
      }
}

(2)将抽象用类作为父类,分别定义各子类

public class Science_book extends Book{

    public Science_book(int bookPage,float discount)
      {  
        super(bookPage,discount);                       //引用父类的构造方法
       }
       public void show_kind()                              //实现抽象方法
       {   
         System.out.println("The book's kind is science");
       }
       public double  getPrice(int bookPage,float discount)      //实现抽象类方法
       {
         return bookPage*0.1*discount;
       }
}

public class Literature_book extends Book{

      public Literature_book(int bookPage,float discount)
      {
         super(bookPage,discount);
       }
       public void show_kind()
       {
         System.out.println("The book's kind is literature");
       }
       public double  getPrice(int bookPage,float discount)
       {
          return bookPage*0.08*discount;
       }
}

public class Teaching_book extends Book{

    public Teaching_book(int bookPage,float discount)
       {
         super(bookPage,discount);
       }
       public void show_kind()
       {
         System.out.println("The book's kind is teaching book");
       }
       public double  getPrice(int bookPage,float discount)
       {
          return bookPage*0.05*discount;
       }
   
}

    

public class BookSell {

    public static void main(String args[])
      {
       Science_book sb=new Science_book(530,0.7f);    //创建科技书类对象
       sb.price=sb.getPrice(530,0.7f);             //引用科技书类方法,计算图书价格
       sb.show_kind();                                  //显示图书种类
       sb.show_price();                               //引用父类方法,显示图书价格
       Literature_book lb=new Literature_book(530,0.7f);      //创建文艺书类对象
       lb.price=lb.getPrice(530,0.7f);
       lb.show_kind();
       lb.show_price();
       Teaching_book tb=new Teaching_book(530,0.7f);     //创建教材类对象
       tb.price=tb.getPrice(530,0.7f);
       tb.show_kind();
       tb.show_price();
      }
}

运行结果

The book's kind is science
This book's price is 37.099999368190765
The book's kind is literature
This book's price is 29.67999949455261
The book's kind is teaching book
This book's price is 18.549999684095383

            8.2接口

                 接口是一组常量和抽象方法的集合。接口只声明抽象方法头,不给出方法体,由实现接口的类实现所声明的抽象方法。

                 8.2.1 声明接口

                     [访问权限] interface 接口名 [extends 父接口名]

                      {

                                   接口体

                      }

                      说明 :1)接口的访问权限是public或默认权限,与类的访问权限类似。

                                  2)一个接口可以继承其他们接口,称为父接口。

                                  3)成员变量表中的成员变量声明形式如下:

                                          成员变量只能是静态、公有的常量,public、static 和final

                                         成员变量名=常量;

                                   4)  成员方法表中的成员方法声明形式如下:

                                           【public】【abstract】 返回值类型 成员方法名(参数表);

以下是一个接口声明:

public interface Shape1

{

public static final PI=3.14159;

public abstract double area();

public abstract double volume( double x);

public abstract void show();

}

               8.2.2 实现接口

                      class 类名 [extends 父类名] implements 接口名列表

                     {

                            类体

                     }

                    说明:1) 一个类可以实现多个接口。

                               2) 实现接口的类必须要实现接口中所有的抽象方法。

                    接口具有如下特点:

                               1)接口与类比较具有特殊发兵 。接口可以多重继承,可以通过使用extends后面的父类接口来定义。

                               2)接口允许没有父接口,即接口不存在最高层。

                               3)接口的方法只能被声明为public,abstract,

                               4)接口中的方法都使用abstract修饰的方法。

例 8-2 实现接口举例。

public interface Shape1 {

    public static final double PI=3.14159;
    public abstract double area();                //计算图形面积
    public abstract double volume( double x);      //计算图形体积
    public abstract void show_height();           //显示图形高度
}

public class Circle1 implements Shape1{

    double radius;
     public Circle1(double r)
      {
        radius =r;
      }
     public double area()
      { return PI*radius*radius;}
     public double volume( double x)
      {return 0;}
     public void show_height()
      {}
    public static void main(String args[])
    {
      Circle1 circle=new Circle1(3);
      System.out.println("Radius="+circle.radius+
            "  Area="+circle.area());
}
}

Radius=3.0  Area=28.274309999999996

                接口与抽象的异同

                 相同点:

                              1)都包含抽象方法,声明多个类共用方法的返回值和参数表        

                             2 )都不能实例化

                             3)都是引用数据类型。

                 不同点:

                             1)   一个类只能继承一个抽象类,是单重继承;一个类可以实现多个接口,具有多重继承功能。

                             2)抽象类及成员具有与普通类一样的访问权限。接口的访问权限有public和默认权限,

                              3)抽象类可以声明成员变量,成员变量的值 可以被更改;接口中只能声明常量。

                             4)抽象类中可以声明抽象方法、普通成员方法及构造方法;接口中只能声明抽象方法。

例8-3 利用接口代替抽象类实现例8-1的功能。

public interface Book {

      abstract  void  show_kind();           //定义抽象方法,显示图书种类
      abstract  double  getPrice(int bookPage,float discount);
}

public class Science_book implements Book{

    int  bookPage;               //图书页码
    float  discount;             //图书折扣
    double  price;
    public Science_book(int bookPage,float discount)
  {
      this.bookPage=bookPage;
      this.discount=discount;
   }
   public void show_kind()
  {
     System.out.println("The book's kind is science");
   }
   public double  getPrice(int bookPage,float discount)
  {
      return bookPage*0.1*discount;
   }
   public void show_price()        //显示价格
  {   
    System.out.println("This book's price is "+price);
  }
}

public class Literature_book implements Book{

       int  bookPage;                   //图书页码
       float  discount;                 //图书折扣
       double  price;
       public Literature_book(int bookPage,float discount)
      {
         this.bookPage=bookPage;
         this.discount=discount;
       }
       public void show_kind()
       {
         System.out.println("The book's kind is literature");
       }
       public double  getPrice(int bookPage,float discount){
          return bookPage*0.08*discount;
       }
       public void show_price(){    //显示价格
         System.out.println("This book's price is "+price);
       }
}

public class Teaching_book implements Book{

       int  bookPage;               //图书页码
       float  discount;             //图书折扣
       double  price;
       public Teaching_book(int bookPage,float discount)
       {
         this.bookPage=bookPage;
         this.discount=discount;
       }
       public void show_kind()
      {
         System.out.println("The book's kind is teaching's book");
       }
       public double  getPrice(int bookPage,float discount){
          return bookPage*0.05*discount;
       }
       public void show_price(){    //显示价格
         System.out.println("This book's price is "+price);
       }
}

public class Show1 {

    public static void main(String args[])
      {
       Science_book bb=new Science_book(530,0.7f);      //创建科技书对象
       bb.price=(int)bb.getPrice(530,0.7f);                 //引用科技书类方法
       bb.show_kind();
       bb.show_price();                                         //引用父类方法
       Literature_book ll=new Literature_book(530,0.7f);
       ll.price=(int)ll.getPrice(530,0.7f);
       ll.show_kind();
       ll.show_price();
       Teaching_book tt=new Teaching_book(530,0.7f);
       tt.price=(int)tt.getPrice(530,0.7f);
       tt.show_kind();
       tt.show_price();
      }
}

       

例8-4 实现接口并继承类举例

            
image

public interface Automobile {

      int i = 5;             // public、static和final可以省略
      void accelent();         // public和abstract可以省略
      void maintain();
      String forward();
      String reverse();
}

public class Little_car implements Automobile{

    public void accelent()
     {
        System.out.println("Little_car.accelent()");
      }
      public void maintain() { }
      public String forward() { return "Little_car  forward"; }
      public String reverse() { return "Little_car  reverse"; }
}

public class Big_car implements Automobile{

    public void accelent()
      {
        System.out.println("Big_car.accelent()");
      }
      public void maintain() { }
      public String forward() { return "Big_car  forward"; }
      public String reverse() { return "Big_car  reverse"; }
}

public class Jeep implements Automobile{

    public void accelent()
      {
        System.out.println("Jeep.accelent()");
      }
      public void maintain() { }
      public String forward() { return "Jeep forward"; }
      public String reverse() { return "Jeep reverse"; }
}

public class Microbus extends Big_car{

    public void accelent()
     {
        System.out.println("Microbus.accelent()");
      }
      public void maintain()
     {
        System.out.println("Microbus.maintain()");
      }
}

public class Bus extends Big_car{

      public String forward() { return "Bus forward"; }
      public String reverse() { return "Bus reverse"; }
}

public class Car {

    public static void main(String[] args)
     {
        Automobile[]  cars=new Automobile[5];
        int i = 0;
        cars[i++]=new Little_car();
        cars[i++]=new Big_car();
        cars[i++]=new Jeep();
        cars[i++]=new Microbus();
        cars[i++]=new Bus();
        for( i=0;i<cars.length;i++)
          cars[i].accelent();
      }
}

运行结果

Little_car.accelent()
Big_car.accelent()
Jeep.accelent()
Microbus.accelent()
Big_car.accelent()

      8.3 包

               包是JAVA提供的组织类和接口的机制,是一组相关类和接口的集合。包提供了类的访问、保护和名字空间管理机制

             8.3.1 包的概念

                     包是一组相关类和接口的集合

             8.3.2 包的声明和导入

                       使用包机制,首先要建立与包名相同的文件夹;再声明类或接口所在的包,并且包中所包含的所有类或接口的字节码文件存放于与包同名的文件夹中;

                       再在程序中导入包中包含的类或接口。

                        1.建立文件夹

                                   包中的所有类或接口编译后生成的字节码文件必须存放于与包同名的文件夹中。

                        2.声明包

                                    包的定义通过关键字package来实现的 ,package语句的一般形式:

                                    package 包名;

                                    如果要声明类或接口位于一个子包中,子包和其父包及祖先包名之间用“.”隔开。

                        3.使用包中的类

                                     一个类如果需要引用其他包中的类或接口,可以采用如下方法:

                                        包名.类名

                                        或

                                        包名.接口名

                                        例如,CLine类要继承位于mypackage包中的CPoint类,其声明格式如下:

                                        public class CLine extends mypackage.CPoint

                                        Graduate类实现mypackage.subpack中接口Person的声明格式如下:

                                        public class Graduate implements mypackage.subpack.Person

                         4.导入包中的类

                                         import 包名.类名

                                           或

                                         import 包名.接口名

                                            或

                                         import 包名.*

                                    
例8-5 包的建立和使用

                在文件Point.java中定义Point类,并声明所在包为pack1

package pack1;

public class Point {

       protected int x, y;    
       public Point()
       { setPoint( 0, 0 ); }
       public Point( int a, int b )
       { setPoint( a, b ); }
       public void setPoint( int a, int b )
        {
          x = a;
          y = b;
        }
       public int getX() { return x; } 
       public int getY() { return y; }
       public String toString()
          { return "[" + x + ", " + y + "]"; }
}

import pack1.Point;

public class PTest {

    public static void main( String args[] )
    {
      Point p = new Point( 72, 115 );
      String output;
      output = "x1=" + p.getX() +", y1=" + p.getY();
      System.out.println(output);
      p.setPoint( 10, 10 );
      output="x2=" + p.getX() +", y2=" + p.getY();
      System.out.println(output);
     }
}

例:8-6 一个包中包含多个类

//MyClass1.java文件
package mypackage;   // 声明包mypackage
public class MyClass1
 {
 protected static final int m=10;
 protected static final int n=20;
 public int sum()
     {
  return m+n;
  }
}

// MyClass2.java文件
package mypackage;    //声明包mypackage
public class MyClass2
 {
 protected  int x=10;
 protected  int y=20;
 public int multi()
 {
  return x*y;
   }
}
//Play.java文件
import mypackage.MyClass1;  // 导入类MyClass1
import mypackage.MyClass2;  // 导入类MyClass2
class Play
 {
 public static void main(String args[])
  {
  MyClass1c1=new MyClass1();
  System.out.println("Sum result is "+c1.sum());
  MyClass2 c2=new MyClass2();
  System.out.println("Multiply result is "+c2.multi());
 }
}

编译bag包中的X1和X2类

键入下列命令,分别对X1和X2类编译:

     javac  X1.java

     javac  X2.java

由于X1.java和X2.java中指定X1和X2类属于bag包,所以编译时,系统自动在当前文件夹下生成子文件夹bag,并将生成的X1.class和X2.class放在当前文件夹的子文件夹bag中

     在PImport.java文件中,引用bag包的X1和X2类

     import bag.X1;          //导入bag包中的X1类

     import bag.X2;          //导入bag包中的X2类  

    

public class PImport

{

  public static void main(String args[])

 {

    X1 aa=new X1(4,5);

    aa.show();

    X2 bb=new X2(10,20);

    bb.show();

  }

}

posted @ 2012-12-28 14:28  elite_2012  阅读(351)  评论(0编辑  收藏  举报