1.引入概念:用之前我们的猫和狗案例,动物举例,动物本身不应该是一个具体的东西,而且呢,动物类中的吃方法,睡觉方法这些都不应该也是具体的。我们现在,把一个不是具体的功能称之为抽象的功能,在Java中称之为抽象方法,而如果类中有抽象的方法,该类就必须定义为抽象类。
2.特点:
1.抽象类和抽象方法必须用abstract关键字修饰
格式 abstract class 类名 {}
public abstract void eat();
/定义一个抽象类 abstract class Animal{ //定义一个抽象的方法,名字叫吃,没有方法体 public abstract void eat(); //下面这样定义抽象方法是错误的,{}代表空方法体,会报错,抽象方法不能有方法体 // public abstract void eat(){}; //定义一个抽象的方法,名字叫睡觉,没有方法体 public abstract void sleep(); }
2.有抽象方法的类一定是抽象类,抽象类不一定有抽象方法,抽象类里面可以有具体的实现方法
//由于类存在抽象方法,该类必须定义为抽象类 //class Demo{ // public abstract void show(); //} abstract class Demo{ public abstract void show(); public void show2(){ System.out.println("这是在抽象类中的具体的方法"); } }
3.抽象类的实例化:
1.按照多态的方式,首先要有继承关系,由具体的子类实例化。多态的形式实例化,我们在这里称之为:抽象类多态
4..抽象类的子态:
1、如果是一个具体的子类,就必须重写所有的抽象方法
2、如果是一个抽象的子类,可以不重写父抽象类的抽象方法,也可以有选择性的重写
package shujia.day1.day5; //抽象方法 abstract class Anmial{ public abstract void sleep(); public abstract void eat(); } //如果是一个具体的子类,就必须重写所有的抽象方法,快捷键alt+enter class Dog extends Anmial{ @Override public void sleep() { System.out.println("侧着睡"); } @Override public void eat() { System.out.println("吃骨头"); } } //如果是一个抽象的子类,可以不重写父抽象类的抽象方法,也可以有选择性的重写 abstract class Cat extends Anmial{ @Override public void eat(){ System.out.println("重写方法"); } } public class AbstractDemo1 { public static void main(String[] args) { //Animal这个类是一个抽象类,而抽象类不能被实例化 // Animal animal = new Animal(); error //用多态的形式进行实例化 Anmial anmial=new Dog(); anmial.sleep(); anmial.eat(); } }
5.抽象类中的特点:
1.成员变量: 可以是变量 也可以是常量
2.构造方法: 有构造方法,但是不能实例化,就是不能创建对象 那么,构造方法的作用是什么呢? 用于子类访问父类数据的初始化
3.成员方法: 可以有抽象方法 限定子类必须完成某些动作
也可以有非抽象方法 提高代码服用性
/* 抽象类中成员的特点: 成员变量:可以是变量,也可以是常量 构造方法:有构造方法 但是抽象类又不能被实例化,有个构造方法有什么用呢? 用于子类访问父类进行初始化 成员方法: 可以是具体的实现方法,也可也是抽象的方法 */ //任何类没有父类就默认是Object的子类 abstract class Anmial2 extends Object{ //抽象类又不能实例化, 用于子类访问父类进行初始化 Anmial2(){}; int num=10;//变量 final int num1=20;//常量 //抽象的方法 public abstract void eat(); //具体的实现方法 public void sleep(){ System.out.println("sleep"); } } class Cat1 extends Anmial2{ @Override public void eat() { System.out.println("fish"); } } public class AbstrctDemo2 { public static void main(String[] args) { Anmial2 anmial2 = new Cat1(); System.out.println(anmial2.num);//10 System.out.println(anmial2.num1);//20 anmial2.eat();//fish anmial2.sleep();//sleep } }
6.abstrct不能和哪些关键词共存:
private 冲突
final 冲突
static 冲突
abstract class Demo2{ public abstract void show(); //非法的修饰符组合: abstract和private // private abstract void show2(); //非法的修饰符组合: abstract和final // final abstract void show3(); //非法的修饰符组合: abstract和static // static abstract void show4(); }
例题:
package com.shujia.java.day12.abstract_code; /* 假如我们在开发一个系统时需要对员工类进行设计,员工包含3个属性:姓名、工号以及工资。 经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。 请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。 分析: 普通员工: 姓名,工号,工资 工作(敲代码) 经理: 姓名,工号,工资,奖金 工作(做PPT) 实现: 抽象的员工类 普通员工类 经理类 */ abstract class Staff{ private String name; private String id; private int salary; public Staff() { } public Staff(String name, String id, int 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 int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public abstract void work(); } class GeneralWorker extends Staff{ public GeneralWorker() { } public GeneralWorker(String name, String id, int salary) { super(name, id, salary); } @Override public void work() { System.out.println("敲代码"); } } class Manager extends Staff{ private int bonus; public Manager() { } public Manager(String name, String id, int salary) { super(name, id, salary); } public int getBonus() { return bonus; } public void setBonus(int bonus) { this.bonus = bonus; } @Override public void work() { System.out.println("做PPT"); } } public class AbstractTest4 { public static void main(String[] args) { Staff s1 = new GeneralWorker("大虎","0001",14000); System.out.println(s1.getName()+"---"+s1.getId()+"---"+s1.getSalary()); s1.work(); Staff s2 = new Manager("小虎","00080",30000); //向下转型使用子类特有的方法 // s2.setBounts(); ((Manager)s2).setBonus(4000000); System.out.println(s2.getName()+"---"+s2.getId()+"---"+s2.getSalary()+"---"+((Manager) s2).getBonus()); s2.work(); } }