一:抽象

   1:引子

   在现实中有各种各样的图形,他们都有面积和周长这样的概念,如果在Java中实现计算各种图形的周长,我们可以定义一个类,里面有许多属性,及一个计算周长的方法,然而我们又不能在这一个方法中把所有图形的周长分别罗列出来,这时我们可以采用抽象类来实现。

   2:何为抽象

   抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象,从多个具有相同特征的类中提炼出抽象类,其具体实现,有继承他的子类去实现。

   3:何时抽象

   在以下任一条成立时,类必须为抽象类

   (1)类中至少有一个抽象方法;

   (2)类中继承了父类的抽象方法,但至少有一个抽象方法没有实现

   (3)类中实现了某一个接口,但没有全部实现接口中的方法

   4:如何定义

   [修饰符] abstract class 类名{//类体}

   5:特别注意:

   (1)抽象类中的方法可以具体实现,也可以不实现,这里的实现指的是方法有方法体,里面可以什么都不做,也可以是一个普通的方法。不实现的方法让子类去实现,子类可以实现也可以不实现,如果子类不实现,则子类也是一个抽象类

   (2)如果一个类有没有实现的方法即抽象方法,则这个类必须为抽象方法

   (3)任何一个类都有构造方法,抽象类也是,只是因为抽象类中存在没有具体实现的方法,所以不能实力化具体的对象,即不能通过new +抽象类类名的形式创建对象。其构造方法是让子类来调用的

   (4)抽象类的使用是采用多态的形式来实现的

   6:具体使用

   ◆定义抽象父类Shape,提供计算周长的方法

public abstract class Shape {//注意关键字
    public abstract double calPermieter();//定义抽象方法,没有方法体
}

   ◆定义矩形子类,继承抽象父类Shape,提供自己的属性,及实现父类的抽象方法

public class Rectangle extends Shape{//注意extends关键字
    private double width;
    private double height;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    public Rectangle() {
        super();
    }
    public Rectangle(double width, double height) {
        super();
        this.width = width;
        this.height = height;
    }
    //抽象方法的具体实现,根据子类的计算规则去实现
    @Override
    public double calPermieter() {
        return 2*(this.width+this.height);
    } 
}

◆定义圆形类,继承抽象父类Shape,提供自己的属性及计算规则

public class Circle extends Shape{
    private double r;   //半径属性
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
    public Circle(double r) {
        super();
        this.r = r;
    }
    public Circle() {
        super();
    }
    //根据自己的计算规则实现继承来的抽象方法
    @Override
    public double calPermieter() {
        return 2*Math.PI*this.r;
    }
}

   ◆测试类,注意具体的使用哦

public class Test {
    public static void main(String[] args) {
        Shape s1 =new Rectangle(20,30);//运用多态实现具体的使用
        double c1 = s1.calPermieter();//矩形的周长的方法的使用
        System.out.println("矩形的周长为:"+c1);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
        Shape cir1 =new Circle(30);//运用多态实现具体的使用
        double c2 = cir1.calPermieter();//圆形的周长的方法的使用
        System.out.println("圆形的周长为:"+c2);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
//      Shape s3 = new Shape();抽象类不能创建子类对象,应通过子类的构造运用多态来实现
    }
}

   ◆结果:

矩形的周长为:100.0
圆形的周长为:188.49555921538757

   二:接口

   1:何为接口

   接口作为类与外界交互的窗口,提供的是一种规范,对于接口的实现者而言,接口规范了实现者必须提供的服务。通俗的说,就是电脑后面的显示器接口,说明了他只能接一个显示器,而没有具体的实现,只有接上了显示器才具有显示的功能。

   2:定义接口

   与java中的类不一样,接口的定义采用的是interface关键字。如下:

   [访问修饰符] interface 接口名 [继承父接口]{

   //0到多个常量

   //0到多个抽象方法

   }

   3:接口的继承

   在Java中类只能实现单继承,且只能实现一个接口。然而,接口也可以实现继承,同样使用extends关键字去继承一个或多个父接口(用逗号隔开),达到多继承,从而弥补类中只能实现的单继承   。定义如下:

   [访问修饰符] interface 接口名 [继承父接口] extends[父接口,父接口,父接口]{

   //0到多个常量

   //0到多个抽象方法

   }

   4:特别注意

   (1)接口中属性值默认的情况下为且只能为public static final的,接口中的方法默认的情况下为且只能为public abstract 类型的,

   (2)由此可见接口中的方法必须在实现接口的类中去实现,即接口中的方法没有实现,只提供了定义,实现接口的类必须实现所有的抽象方法

   (3)接口中没有main方法,因为main方法有具体的实现

(4)接口中没有构造方法,不能通过new 创建对象,只能通过子类来实现

  (5)java中的类与接口之间的相互关系

   类----类:单继承,extends        接口----接口:多继承/单继承,extends      类----接口:实现,implements

   (6)类之间的强制转换时,会检测类之间的继承关系,而转换为接口时不会检测实现关系

   5:具体使用:

   ◆定义接口

public interface  TestInterface{
    int MAX_NUM=1000;//接口中的属性,默认为static final类型
    void test();//接口中的方法,默认为abstract类型的
}

   a:验证属性的默认类型

public class Test implements TestInterface{//注意implements关键字的使用
    @Override
    public void test() {//必须实现的方法,否则编译时异常,说明在接口中是抽象方法
        System.out.println("我是接口中的抽象方法");
    }
                                                                                                                                                                                                                                          
    public static void main(String[] args) {
        System.out.println("我是接口中的静态不可变常量:"+TestInterface.MAX_NUM);
        //可以直接使用接口名.属性名来获取属性值,说明属性值是static修饰的
//      TestInterface.MAX_NUM=10009;编译时异常,说明这个属性值不可以改动,所以为final修饰的
                                                                                                                                                                                                                                              
    } 
}

 结果:

我是接口中的静态不可变常量:1000

   b:接口的多继承

   ◆定义电话,听,说的三个接口,让电话具备听和说的双重功能

public interface Phone extends Listen,Say{
    //定义Phone接口,继承了下面的两个接口,说明它具有听和说的双重功能
}
interface Listen{
    //定义”听“接口,表明实现该接口的类或继承该接口的接口具有听的功能
}
interface Say{
    //定义”说”接口,表明实现该接口的类或继承该接口的接口具有说的功能
}

   c:接口的使用

   接口可以被类实现被接口继承,实现接口的类的定义

   [访问修饰符] class 类名 [extends 父类] implements接口1,接口2{//代码块}

   ◆定义接口,提供学习的功能

public interface Study{
    public abstract void study();//抽象方法
}

  ◆定义具体的实现接口的类

public class Person implements Study{
    public void study() {
        System.out.println("我是实现接口的Person类,所以必须实现接口中的抽象方法");      
    }
                                                                                                      
    public static void main(String[] args) {
        Person p = new Person();//创建具体实现类的对象
        p.study();//调用实现的方法
    }
}

   ◆结果:

我是实现接口的Person类,所以必须实现接口中的抽象方法


   三:接口与抽象

   1:共同特征

   (1)都不能被实例化。

   (2)都包含抽象方法。继承抽象类的类可以选择实现或者不实现,不实现则子类为抽象类,实现接口的类必须实现接口中所有的抽象方法

   2:二者区别

   (1)接口中只能有抽象方法,抽象类中至少有一个抽象方法

   (2)接口中不能定义静态方法,抽象类中则可以定义静态方法

   (3)接口中的属性只能是静态常量,不能有普通属性,抽象类中则可以定义普通属性及静态常量


   Java中还有很多这样的难以区分的东西,熟练理解,才是硬道理。JAVA中的抽象与接口_接口