注册 登录
编程论坛 J2EE论坛

java中的抽象类abstract怎么使用?

专注的蝴蝶 发布于 2019-09-23 13:47, 4993 次点击
抽象类概述
当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的功能具体实现方式,那么这些方法都有具体的方法体。
但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。比如一个图形类应该有一个求周长的方法,但是不同的图形求周长的算法不一样。那该怎么办呢?
分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是方法功能声明相同,但方法功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
1、 案例代码:
package com.itheima_01;
/*
 * abstract:关键字,用于修饰方法和类
 * 抽象方法:不同类的方法是相似,但是具体内容又不太一样,所以我们只能抽取他的声明,没有具体的方法体,没有具体方法体的方法就是抽象方法
 * 抽象类:有抽象方法的类必须是抽象类
 *  
 * 注意:一个类继承了抽象类需要重写他所有的抽象方法,否则这个类就得是抽象类
 */
public class AbstractDemo {
}
abstract class Animal1 {
    public abstract void eat();
    //非抽象方法子类可以不重写
    public void run() {     
    }
}
class Cat1 extends Animal1 {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");     
    }
    /*public void eat() {
        System.out.println("猫吃鱼");
    }*/
}
abstract class Dog1 extends Animal1 {
    /*public void eat() {
        System.out.println("狗吃屎");
    }*/
}
2、 抽象类的特点
 抽象类的特点:
   抽象方法只能在抽象类里面
   抽象类和抽象方法必须被abstract修饰
   抽象类不能创建对象(不能实例化)
   抽象类中可以有非抽象的方法
   抽象类和类的关系也是继承
   一个类继承了抽象类要么重写所有的抽象方法,要么他自己是抽象类
案例代码:
package com.itheima_01;
/*
 * 抽象类的特点:
 *         抽象方法只能在抽象类里面
 *         抽象类和抽象方法必须被abstract修饰
 *         抽象类不能创建对象(不能实例化)
 *         抽象类中可以有非抽象的方法
 *         抽象类和类的关系也是继承
 *         一个类继承了抽象类要么重写所有的抽象方法,要么他自己是抽象类
 */
public class AbstractDemo2 {
    public static void main(String[] args) {
        //Animal a = new Animal();
    }
}
abstract class Animal2 {
    public abstract void eat();
    public void run() {     
    }
}
class Cat2 extends Animal2 {
    @Override
    public void eat() {
        // TODO Auto-generated method stub
    }
}
3、抽象类的成员的特点
A:抽象类的成员特点:
   成员变量
   可以有成员变量
   可以有常量
   成员方法
   可以有抽象方法
   可以有非抽象方法
   构造方法
   可以有构造方法的,需要对抽象类的成员变量进行初始化
案例代码:
package com.itheima_01;
/*
 * 抽象类的成员特点:
 *         成员变量
 *             可以有成员变量
 *             可以有常量
 *         成员方法
 *             可以有抽象方法
 *             可以有非抽象方法
 *         构造方法
 *             可以有构造方法的,需要对抽象类的成员变量进行初始化
 *  
 * final:修饰类、成员变量、成员方法
 */
public class AbstractDemo3 {
    public static void main(String[] args) {
        Dog d = new Dog();
        d.barking();
    }
}
abstract class Animal {
    String name = "哮天犬";
    final int num = 10;
    public Animal() {
        System.out.println("我是抽象类的构造方法");
    }
    public abstract void eat();
    public void run() {}
}
class Dog extends Animal {
    public void barking() {
        System.out.println(name);
        System.out.println(num);
    }
    @Override
    public void eat() {
        // TODO Auto-generated method stub     
    }
}
4、抽象类的细节
 A:抽象类关键字abstract可以和哪些关键字共存?
1.private:
私有的方法子类是无法继承到的,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。
2.final:  
  抽象类不能和final共存,因为抽象类自身无法创建对象,我们需要通过子类创建对象,一旦抽象类使用final关键字,那么抽象类就没有子类
  抽象方法不能和final共存,因为抽象方法后期需要被子类重写,一旦加final无法重写   
3.static:
  抽象方法不能和static关键字共存,因为一旦加static我们就可以通过类名直接访问抽象方法,由于抽象方法没有方法体,没有任何意义,也不允许这样做
B:抽象类中是否可以不定义抽象方法?
是可以的,那这个抽象类的存在到底有什么意义呢?不让该类创建对象,方法可以直接让子类去使用
C:抽象类是否有构造函数?
有,抽象类的构造函数,是由子类的super语句来调用,用于给抽象类中的成员初始化
用关键字abstract修饰的方法称为抽象方法。
对于抽象方法,只允许声明,不允许实现(没有方法体),而且不允许finnal和abstract修饰同一方法或类,也不允许static修饰abstr方法,即abstract方法必须是实列方法。
abstra类不能用new 运算符创建对象
abstract类的子类必需重写abstra类中的方法
abstra类的对象作为上转型对象
abstract class GirlFriend {
    abstract void speak();
    abstract void cooking();
}
class ChinaGirlFriend extends GirlFriend {
    void speak() {
        System.out.println("你好");
    }
    void cooking() {
        System.out.println("水煮鱼");
    }
}
class AmericanGirlFriend extends GirlFriend {
    void speak() {
        System.out.println("Hello!");
    }
    void cooking() {
        System.out.println("Roast beef");
    }
}
class Boy {
    GirlFriend friend;
    void SetGirFriend(GirlFriend f) {
        friend = f;
    }
    void showGirlFriend() {
        friend.speak();
        friend.cooking();
    }
}
public class Test {
    public static void main(String[] args) {
        GirlFriend girl = new ChinaGirlFriend(); //girl is Upper  Transition Object
        Boy boy = new Boy();
        boy.SetGirFriend(girl);
        boy.showGirlFriend();
        girl = new AmericanGirlFriend();
        boy.SetGirFriend(girl);
        boy.showGirlFriend();
    }
}
面向抽象编程
在程序设计中我们经常会使用abstra类,因为它只关心操作,而不在意具体实现细节。
所谓的面向抽象编程,是指设计某种重要的类时,不让该类面向具体的类,而是面向抽象类。
import java.awt.*;
public class Test {
    public static void main(String[] args) {
        double a,b;
        Pillar pillar;
        Geometry bottom=null;
        pillar=new Pillar(bottom,100);
        System.out.println("体积"+pillar.getVolume());
        bottom=new Rectangle(12,22);
        pillar=new Pillar(bottom,58);
        System.out.println("体积"+pillar.getVolume());
        bottom=new Circle(10);
        pillar=new Pillar(bottom,58);
        System.out.println("体积"+pillar.getVolume());
    }
}
abstract class Geometry {
    abstract double getArea();
}
class  Pillar {
    Geometry bottom;  //bottom is a variable by  the abstract class geometry
    double height;
 
    Pillar(Geometry bottom, double height) {
        this.bottom = bottom;
        this.height = height;
    }
    public double getVolume() {
        if (bottom == null) {
            System.out.println("没有底,无法计算面积!");
            return  -1;
        }
        return bottom.getArea() * height;  //Bottom can call the getArea method that the subclass overrides
    }
}
class Circle extends Geometry {
    double r;
    Circle(double r) {
        this.r = r;
    }
    public double getArea() {
        return (3.14 * 3.14 * r);
    }
}
class Rectangle extends Geometry{
    double a, b;
    Rectangle(double a, double b) {
        this.a = a;
        this.b = b;
    }
    double getArea() {
        return a * b;
    }
}
为什么使用抽象类
首先做一个分析如下:
1:定义Dog类
   有颜色属性和叫的方法
2:定义Bird类
   有颜色属性和叫的方法
3:定义其父类Animal
1:抽取共性颜色属性和叫的方法
   1:颜色的属性可以使用默认初始化值。
   2:叫的方法在父类中如何定义?
      1:狗是旺旺
      2:鸟是叽叽喳喳
      3:可以将父类的方法定义为狗叫让鸟继承父类重写叫的方法
            1:鸟怎么确定是否要重写父类方法。
            2:不重写,编译和运行都没有问题,只是执行鸟叫的方法就会出现狗叫
      4:父类的方法很难确定。
上方描述代码如下:
function(){
class Animal {
    String color;
     void shout(){
         //如何定义呢?是旺旺还是叽叽喳喳?
     }
}
class Dog extends Animal {
    void shout() {
        System.out.println("旺旺");
    }
}
class Bird extends Animal {
    void shout() {
        System.out.println("叽叽喳喳");
    }
}
那么此时使用abstract能够解决这个问题 。
4:抽象类
1:当描述一个类的时候,如果不能确定功能函数如何定义,那么该类就可以定义为抽象类,功能函数应该描述为抽象函数。
5:抽象类的实现方式
       1:定义animal类
              1:定义叫的方法,无法确定方法体,不写方法体
                 1:public void shout (); 编译失败
              2:根据提示在shout的方法加入abstract修饰
                 1:编译失败,有新的提示
              3:根据提示将类加入abstract修饰
                 1:编译通过
abstract class Animal {
    String color;
    abstract void shout();
}
class Dog extends Animal {
    void shout() {
        System.out.println("旺旺");
    }
}
class Bird extends Animal {
    void shout() {
        System.out.println("叽叽喳喳");
    }
}
6:抽象类的特点
       1:有抽象函数的类,该类一定是抽象类。
       2:抽象类中不一定要有抽象函数。
       3:抽象类不能使用new创建对象
          1:创建对象,使用对象的功能,抽象类的方法,没有方法体。
       4:抽象类主要为了提高代码的复用性,让子类继承来使用。
       5:编译器强制子类实现抽象类父类的未实现的方法。
          1:可以不实现,前提是子类的也要声明为抽象的。
7:抽象的优点
       1:提高代码复用性
       2:强制子类实现父类中没有实现的功能
       3:提高代码的扩展性,便于后期的代码维护
8:抽象类不能创建对象,那么抽象类中是否有构造函数?
抽象类中一定有构造函数。主要为了初始化抽象类中的属性。通常由子类实现。
9:final和abstract是否可以同时修饰一个类?
       一定不能同时修饰。
abstract class Animal {
    String name;
    // 抽象类可以有构造函数
    Animal() {
    }
    Animal(String name) {
        this.name = name;
    }
    abstract void shout();
}
class Dog extends Animal {
    Dog() {
    }
    Dog(String name) {
        super(name);
    }
    void shout() {
        System.out.println("旺旺");
    }
}
class Demo3 {
    public static void main(String[] args) {
        // 抽象类不能创建对象
        // Animal a=new Animal();
        Dog d = new Dog("旺财");
       System.out.println();
    }
}
0 回复
1