java的抽象类

一、抽象类概述:
    

  我们知道,类用来模拟现实事物。一个类可以模拟一类事物,而某个类的一个实例化对象可以模拟某个属于该类的具体的事物。类中描绘了该类所有对象共同的特性,当一个类中给出的信息足够全面时,我们就可以实例化该类;比方说,在Dog类中定义了name,age,fur_color,sex等属性,以及habit,eat等行为时,我们就可以创建一个Dog类对象,来模拟某个具体的Dog,比如你家的宠物狗,或者是神犬小七等。

  但是,当一个类中给出的信息不够全面时,(比方说有无法确定的行为),它给出的信息不足以描绘出一个具体的对象,这时我们往往不会实例化该类,这种类就是抽象类打个比方,对于Animal类,是,所有的动物都有吃喝的行为,定义eat方法可以描述动物“吃”这一行为,但是每种动物吃的都不一样,因此一个eat方法并不能准确描述吃什么,怎么吃。这时Animal给出的信息就不足够描述一个对象,我们就不能去实例化Animal类。
   在Java中,我们通过使用abstract关键字来修饰该方法,这个方法就时抽象方法,在类前添加关键字abstract(抽象的)来定义抽象类。如下图所示 : 

abstract class Animal {
    private String name;
    public Animal(String name) {
        this.name = name;
    }
    //实现这一步,没有意义,即出现了父类方法不确定的问题,
    // 此时就考虑将该方法 设计为  抽象(abstract)方法
    //所谓抽象方法 就是指 没有实现的方法(没有方法体)
    //当一个类中存在抽象方法时,需要将该类 声明为 abstract类
    //一般来说,抽象类会被继承,由其子类来实现抽象方法
    public abstract void eat();
}

 二、抽象方法 : 


        1.概述 : 


                我们将“只有方法声明,没有方法体”的一类方法统称为抽象方法,抽象方法用关键字abstract修饰。需要注意的是,如果一个方法已经确定是抽象类,那么它绝不能再有方法体,即不能出现大括号,而是只需要在()后面添加一个分号即可,否则IDEA会提示报错信息

还要注意一点,如果某个类中已经出现了抽象方法,那这个类必须定义成抽象类, 也就是说,拥有抽象方法的类一定是抽象类;但是抽象类不一定有抽象方法。 

       2.应用 : 


                当父类需要定义一个方法,却不能明确该方法的具体实现细节时,可以将该方法定义为abstract,具体实现细节延迟到子类。(让子类重写这个方法)
                就比如我们刚才说的——Animal类中的eat() 方法,我们可以先将其定义为抽象类,然后在子类中,比如说Dog类中重写eat() 方法,给出对Dog类对象“吃”这一行为的一些具体描述。
                up以Animal类,Dog类和Test类为例,代码如下 : 

package knowledge.polymorphism.about_abstract.introduction;
 
public abstract class Animal {   /** 父类 */
    //将Animal类中的eat() 方法定义为抽象类,具体实现延迟到子类。
    public abstract void eat();
}
 
class Dog extends Animal {      /** 子类 */
    //子类重写父类的抽象方法,也称为子类实现了该抽象方法。
    public void eat() {
        System.out.println("狗是杂食性动物,喜食肉类,喂养时应该以动物蛋白为主,素食为辅。");
    }
}
 
class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();
    }
}

   3.特点 : 

     ①若父类中定义了一个抽象方法,要求其所有非抽象子类都必须重写该抽象方法。否则IDEA会报错,如下图所示 : 

     ②前面我们说了,抽象方法用abstract关键字修饰。这里再补充一点——抽象方法不能再使用private,final 或者static关键字来修饰,即abstract不能与private,final或static共同出现,这是因为定义抽象方法的目的就是想将方法的具体实现延迟到子类,最终是要被子类重写的,而private,final,static这几个关键字都和“方法重写”的目的背道而驰。
                如果你固执己见,非要让abstract和这几个关键字一同出现,IDEA也是毫不客气,直接报错,如下图所示 : 

三、抽象类特点 : 

         1.关于abstract关键字 : 

                      abstract关键字只能用于修饰类和方法,用于声明抽象类和抽象方法。其中,抽象类必须使用abstract关键字修饰声明时格式如下 : 

访问权限修饰符  abstract  class  类名{ // }

访问权限修饰符  abstract  返回值类型  方法名(形参列表);

//抽象类
public abstract class Animal {
    //抽象方法
    public abstract void eat();        //抽象方法最后加一个分号即可,不可以有大括号。
}

          2.抽象类不能被实例化,只能创建其子类对象

                       即,我们不能创建抽象类对象(这里的对象指的是堆空间中真正的对象,即不能“new 抽象类”),原因我们在开篇抽象类的概述中也提到了,这里不再赘述。如果你头铁,非要创                        建抽象类对象,IDEA也不是吃素的,直接报错,如下图所示 : 

                               当然,如果抽象类的子类没有用abstract关键字修饰,那么我们可以创建其子类对象,如下图所示 :  

             3.抽象类子类的两个选择 : 

                               如果某个类继承了一个抽象类,那么这个类有两个选择——要么实现父类所有的抽象方法,要么子类本身也定义成抽象类

                               当然,肯定也不会是瞎jb想定义成抽象类就定义成抽象类的😂,要满足我们我们上面所说的定义抽象类的条件——类中提供的信息不足以描述一个对象,或者类中有无法确                                   定的行为需要延迟到子类实现。

                               还是给大家举个栗子。up现在在character包下创建一个Food类,将Food类定义为抽象类,并定义showNutrition()抽象方法,该方法将来要打印出食物的主要营养,具体实                                   现延迟到子类;然后分别创建子类Meat类和Fruit类去继承Food类,我们在Meat类中重写Food类的showNutrition() 方法,使其打印出肉类的主要营养价值;同时,另一个子                                类Fruit类不去实现showNutrition() 方法,而是将其定义为抽象类。最后,以Test类为测试类,在测试类中创建子类对象并调用showNutrition() 方法。

package knowledge.polymorphism.about_abstract.character;
 
public abstract class Food {            /** 父类 : Food类 */
    //记住,抽象方法没有方法体
    public abstract void showNutrition();
}
 
class Meat extends Food {               /** 子类 : Meat类 */
    @Override
    public void showNutrition() {
        System.out.println("肉类是蛋白质、脂肪、维生素B2、维生素B1、烟酸和铁的重要来源。");
    }
}
 
abstract class Fruit extends Food {     /** 子类 : Fruit类 */
}
    
class Test {                            /** 测试类 : Test类 */
    public static void main(String[] args) {
        Meat meat = new Meat();
        meat.showNutrition();
    }
}

我们也可以再定义一个CiLi类表示水果中的刺梨,然后让刺梨类去继承Fruit类,并在CiLi类中去实现showNutrition() 方法;Fruit类不变,Test类和CiLi类代码如下 : 

class CiLi extends Fruit {
    @Override
    public void showNutrition() {
        System.out.println("刺梨是当之无愧的水果界的VC之王,VC含量高达2585mg/100g!");
    }
}
 
class Test {
    public static void main(String[] args) {/** 测试类 : Test类 */
        Meat meat = new Meat();
        meat.showNutrition();
        System.out.println("----------------------------------------");
 
        CiLi ciLi = new CiLi();
        ciLi.showNutrition();
    }
}

四、抽象类的成员 : 

抽象类本质也是类

1.成员变量 : 

   抽象类既可以有静态的成员变量,也可以有非静态的成员变量
              既可以有静态的成员常量,也可以有非静态的成员常量。 

 2.成员方法 : 

抽象类既可以有(非私有的)抽象方法(注意抽象方法一定是非私有非静态非final,因为abstract关键字与private关键字,final关键字,static关键字不能同时存在);

        也可以有非抽象方法(非抽象方法就可以用private,final和static关键字来修饰了,具体使用时,根据实际需求合理应用)。
 

 3.构造器 : 

抽象类可以和非抽象类一样拥有构造器,并且支持构造器的重载。

4.总结 : 

        其实吧,说上面一大堆都是废话😂。

        抽象类中的成员只比非抽象类多一种——抽象方法。其他都和非抽象类一样。

        大家只要记住抽象方法怎么写,怎么用就彳亍了。😎

五、练习

package com.lmdedu.abstract_;

public class AbstractExercise {
    public static void main(String[] args) {
        CommonEmployee jjf = new CommonEmployee("jjf", "118", 5000);
        jjf.work();

        Manager lmd = new Manager("lmd", "001", 50000, 50000);
        lmd.work();
    }
}
//将父类 Employee定义为抽象类
abstract class Employee {//父类
    private String name;
    private String id;
    private double salary;

    public Employee(String name, String id, double salary) {
        this.name = name;
        this.id = id;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    //抽象方法work
    public abstract void work() ;
}

class CommonEmployee extends Employee{//子类
    public CommonEmployee(String name, String id, double salary) {
        super(name, id, salary);
    }
    
    //在子类中重写抽象类work 
    @Override
    public void work() {
        System.out.println("普通员工" + getName() +"工作中");
    }
}

class Manager extends Employee{//子类
    private double bonus;

    public Manager(String name, String id, double salary, double bonus) {
        super(name, id, salary);
        this.bonus = bonus;
    }

    public double getBonus() {
        return bonus;
    }

    public void setBonus(double bonus) {
        this.bonus = bonus;
    }
    //在子类中重写抽象类work 
    @Override
    public void work() {
        System.out.println("经理" + getName() + "工作中");
    }
}

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值