zoukankan      html  css  js  c++  java
  • 抽象类和接口

    一、抽象类

    抽象类(abstract class):不能实例化的类,使用关键字abstract修饰,含有抽象方法(abstract method)。

    抽象方法(abstract method):在方法头中使用关键字abstract修饰,只有函数的声明定义,没有函数体的方法。

         包含抽象方法的类必须是抽象类,抽象类可以不包含抽象方法。

    之前有写过一个几何、圆、矩形的类,现在改写几何类为抽象类,包括求面积、求周长这两个抽象方法:

    package demo;
    
    import java.util.Date;
    
    /**
     * 定义一个几何抽象类
     * Created by luts on 2015/11/29.
     */
    public abstract class GeometricObject {
        private String name = null; //几何形状名字
        private String color = "white";
        private boolean filled = false;
        private java.util.Date dateCreated;
    
        //无参构造器
        protected GeometricObject(){
            dateCreated = new java.util.Date();
        }
    
        //含参构造器
        protected GeometricObject(String name, String color, boolean filled){
            this.name = name;
            this.color = color;
            this.filled = filled;
            dateCreated = new java.util.Date();
        }
    
    
        public String getName() {
            return name;
        }
    
        public void setName(String name){
            this.name = name;
        }
    
        public String getColor(){
            return color;
        }
        public void setColor(String color) {
            this.color = color;
        }
    
        public boolean isFilled() {
            return filled;
        }
    
        public void setFilled(boolean filled){
            this.filled = filled;
        }
    
        public Date getDateCreated() {
            return dateCreated;
        }
    
        public String toString(){
            return "created on " + dateCreated + "
    color: " + color + " and filled: " + filled ;
        }
    
        public abstract double getArea();  //求面积的抽象函数,在子类中实现
    
        public abstract double getPerimeter(); //求周长的抽象函数,在子类中实现
    }
     1 package demo;
     2 
     3 /**
     4  * 圆类,继承于几何类
     5  * Created by luts on 2015/11/29.
     6  */
     7 
     8 public class Circle extends GeometricObject {
     9     private double radius;
    10 
    11     public Circle(){
    12 
    13     }
    14 
    15     public Circle(String name, double newRadius){
    16         this.setName(name);
    17         this.radius = newRadius;
    18     }
    19 
    20     public Circle(double newRadius, String newColor, boolean newFilled){
    21         this.radius = newRadius;
    22         setColor(newColor);
    23         setFilled(newFilled);
    24     }
    25 
    26     public double getRadius(){
    27         return radius;
    28     }
    29 
    30     public double getArea(){
    31         return radius * radius * Math.PI;
    32     }
    33 
    34     public double getDiameter(){
    35         return 2 * radius;
    36     }
    37 
    38     public double getPerimeter(){
    39         return 2* radius * Math.PI;
    40     }
    41 
    42     public void printCircle(){
    43         System.out.println("The circle is creadted " + getDateCreated() + " and the raius is " + radius);
    44     }
    45 }
     1 package demo;
     2 
     3 /**
     4  * 矩形类,继承于几何类
     5  * Created by luts on 2015/11/29.
     6  */
     7 
     8 public class Rectangle extends GeometricObject{
     9     private double width;
    10     private double height;
    11 
    12     public Rectangle(){
    13 
    14     }
    15 
    16     public Rectangle(String name, double newWidth, double newHeight){
    17         this.setName(name);
    18         this.width = newWidth;
    19         this.height = newHeight;
    20     }
    21 
    22     public  Rectangle(double newWidth, double newHeight, String newColor, boolean newFilled){
    23         this.width = newWidth;
    24         this.height = newHeight;
    25         setColor(newColor);
    26         setFilled(newFilled);
    27     }
    28 
    29     public double getWidth(){
    30         return width;
    31     }
    32 
    33     public void setWidth(double newWidth){
    34         this.width = newWidth;
    35     }
    36 
    37     public double getHeight(){
    38         return height;
    39     }
    40 
    41     public void setHeight(double newHeight){
    42         this.height = newHeight;
    43     }
    44 
    45     public double getArea(){
    46         return width * height;
    47     }
    48 
    49     public double getPerimeter(){
    50         return 2 * (width + height);
    51     }
    52 }
     1 package demo;
     2 
     3 /**
     4  * Created by luts on 2015/11/29.
     5  */
     6 
     7 public class TestGeometericObject {
     8     public static void main(String[] args){
     9         GeometricObject geoObject1 = new Circle("Circle",5); //多态 父类类型指向子类实例的引用
    10         GeometricObject geoObject2 = new Rectangle("Rectangle", 5, 3);
    11 
    12         System.out.println("The two objects have the same area ?" + equalsArea(geoObject1, geoObject2));
    13 
    14         displayGeometricObject(geoObject1);
    15 
    16         displayGeometricObject(geoObject2);
    17     }
    18 
    19 
    20     public static boolean equalsArea(GeometricObject obj1, GeometricObject obj2){
    21         return obj1.getArea() == obj2.getArea();
    22     }
    23 
    24     public static void displayGeometricObject(GeometricObject object){
    25         System.out.println();
    26         System.out.println("The new " + object.getName()+ "'s area is: " + object.getArea());
    27         System.out.println("The new " + object.getName()+ "'perimeter is: " + object.getPerimeter());
    28     }
    29 }

    输出:

    The two objects have the same area ?false
    
    The new Circle's area is: 78.53981633974483
    The new Circle'perimeter is: 31.41592653589793
    
    The new Rectangle's area is: 15.0
    The new Rectangle'perimeter is: 16.0

        上述例子中,如果GeometricObject 类中没有定义getArea()方法,就不能在程序中定义equalsArea方法来计算这两个几何对象的面积是否相等。JVM根据运行时的实际对象动态地调用getArea方法(多态)

        · 抽象类与常规类很相似,但是不能使用new操作符创建其实例对象,可以声明引用变量

      · 抽象方法只有定义没有实现,子类提供具体的实现方式。一个包含抽象方法的类必须声明为抽象类。

      · 抽象类的构造方法定义为protected,因为只能被子类使用。创建一个具体的子类的时候,其父类的构造方法被调用,以初始化父类中定义的数据域。

    一些值得注意的:

      · 抽象方法不能包含在非抽象类中。如果抽象父类的子类不能实现所以的抽象方法,那么子类也应该声明为抽象类。也就是说在抽象类扩展的子类中,必须实现所有的抽象方法。抽象方法是非静态的。

      · 抽象类不能使用new操作符来初始化。但是仍然可以定义其构造方法,这个构造方法在子类中被调用。

      · 即使父类是具体的,这个子类也可以是抽象。例如Object是具体的,但是它的子类如上例中的GeometricObject可以是抽象的。

      · 子类可以覆盖父类的方法并将其定义为abstract。也就是当父类的方法在子类的方法实现是没有意义的时候,可以将其覆盖声明为抽象方法,这时子类必须定义为abstract。

      · 不能使用new操作符从一个抽象类创建一个实例,但是抽象类可以作为一种数据类型。

    二、接口(interface)

      接口(interface)是一种与类相似的结构,只包含常量和抽象方法,目的是指明多个对象的共同行为。(比如,通过使用正确的接口,可以指明这些对象是可比较的,可食用的或可克隆的)。

      

      接口的语法结构:

    1 修饰符  interface 接口名{
    2         //常量名
    3         //方法签名
    4     }
    5     
    6  
    7 public interfaceEdibleInterface{
    8   public abstract String howToEat();
    9 }

      · 接口被看成是一种特殊的类,与抽象类类似,不能使用new操作符创建接口实例,可以使用接口作为变量的数据类型或类型转换的结果等。

     例子:使用接口EdibleInterface来明确一个对象是否可食用。需要使用implements关键字让对象的类实现这个接口。类和接口之间的关系成为接口继承(interface inheritance)。

    1 package demo;
    2 
    3 /**
    4  * Created by luts on 2015/11/30.
    5  */
    6 public abstract interface EdibleInterface {
    7     //Describe hoe to eat
    8     public abstract String howToEat();
    9 }
     1 package demo;
     2 
     3 import java.util.Objects;
     4 
     5 /**
     6  * Created by luts on 2015/11/30.
     7  */
     8 public class TestEdible {
     9     public static void main(String[] args){
    10         Object[] objects = {new Tiger(), new Chicken(), new Apple()};
    11         for (int i = 0; i < objects.length; i++){
    12             if (objects[i] instanceof EdibleInterface)
    13                 System.out.println(((EdibleInterface) objects[i]).howToEat());
    14         }
    15     }
    16 }
    17 
    18 class Animal{
    19     private String name;
    20 
    21     public String getName() {
    22         return name;
    23     }
    24 
    25     public void setName(String name) {
    26         this.name = name;
    27     }
    28 }
    29 
    30 class Chicken extends Animal implements EdibleInterface{
    31     public String howToEat(){
    32         return "Chiken: Fry it";
    33     }
    34 }
    35 
    36 class Tiger extends Animal {
    37 
    38 }
    39 
    40 abstract class Firut implements EdibleInterface{
    41 
    42 }
    43 
    44 class Apple extends Firut{
    45     @Override
    46     public String howToEat() {
    47         return "Apple: Make apple cider";
    48     }
    49 }

       · 当一个类实现接口的时候,该类实现了定义在接口中的所有带确切签名和返回值类型的方法。如果继承接口的类不实现抽象方法,那么必须声明为抽象类,如abstract Fruit类。

      · 接口中所有的数据域都是public final static。所有的方法都是public abstract,java允许忽略这些修饰符。

      · 接口内定义的常量可以使用语法“接口名.常量名”来访问。

    ActionListener接口例子:

     1 package demo;
     2 
     3 import javax.swing.*;
     4 import java.awt.event.ActionEvent;
     5 import java.awt.event.ActionListener;
     6 
     7 /**
     8  * Created by luts on 2015/11/30.
     9  */
    10 public class HandleEvent extends JFrame{
    11     public HandleEvent(){
    12         //创建两个按钮
    13         JButton jbtOK = new JButton("OK");
    14         JButton jbtCancel = new JButton("Cancel");
    15 
    16         JPanel panel = new JPanel();
    17         panel.add(jbtOK);
    18         panel.add(jbtCancel);
    19 
    20         add(panel);
    21 
    22         OKListenerClass listener1 = new OKListenerClass();
    23         CancelListenrClass listener2 = new CancelListenrClass();
    24         jbtOK.addActionListener(listener1);
    25         jbtCancel.addActionListener(listener2);
    26 
    27     }
    28 
    29     public static void main(String [] args){
    30         JFrame frame = new HandleEvent();
    31         frame.setTitle("Handle Event");
    32         frame.setSize(200, 150);
    33         frame.setLocation(200, 100);
    34         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    35         frame.setVisible(true);
    36     }
    37 }
    38 
    39 class OKListenerClass implements ActionListener{
    40     public void actionPerformed(ActionEvent e){
    41         System.out.println("OK button clicked");
    42     }
    43 }
    44 
    45 class CancelListenrClass implements ActionListener{
    46     public void actionPerformed(ActionEvent e){
    47         System.out.println("Cancel button clicked");
    48     }
    49 }

    输出:

    Cancel button clicked
    Cancel button clicked
    OK button clicked
    Cancel button clicked
    OK button clicked
    OK button clicked

    三、接口和抽象类

      变量 构造方法 方法
    抽象类 无限制 子类通过构造方法链调用构造方法,抽象类不能使用new操作符实例化 无限制(可为抽象方法或非抽象方法),一般都含有抽象方法
    接口 所有变量必须是 public static final 没有构造方法,接口不能用new操作符实例化 所有方法必须是公共的抽象实例方法

       · java只允许为类的扩展做单一的继承,但是允许使用接口做多重扩展

    public class NewClass extends BaseClass implements Interface1, ..., InterfaceN{
       ....
    }

      · 利用关键字extends,接口可以继承其他接口。这样的接口称为子接口(subinterface)。

    public interface NewInterface extends Interface1, ..., InterfaceN{
      .....
    }

      一个类实现上述的NewInterface必须实现Interface1, ..., InterfaceN中定义的所有抽象方法。接口可以扩展其他接口,但不能扩展类,一个类可以扩展它的父类同时实现多个接口。

      · 所有类共享同一个根类Object,但是接口没有共同的根

      · 与类类似,接口也可以定义一种类型。一个接口类型的变量可以引用任何实现该接口的类的实例。也就是,一个类如果实现了一个接口,那么这个接口就类似于该类的一个父类。

    接口和抽象类都是用来确定多个对象的共同特征的。那么什么时候使用接口,什么时候使用抽象类呢?

      一般来说,详细描述父子关系的强是关系(strong is-a relationship)应该用类建模。弱是关系(weak is-a relationship)也称为类属关系(is-kind-relationship),它表明对象拥有某种属性。弱是关系可以用接口来建模

  • 相关阅读:
    安装 macbook 双系统( OS X 和 Ubuntu )
    微信小程序初探
    [Javascript] Promise
    [AS/400] 基本概念
    [AS/400] Control Language(CL) 基本概念
    [AS/400] Control Language
    [github] 创建个人网页
    [tools] sublime 使用记录
    [Java] TreeMap
    exe转msi
  • 原文地址:https://www.cnblogs.com/luts/p/5004982.html
Copyright © 2011-2022 走看看