抽象类的特点:
1、抽象类和抽象方法必须用abstract关键字修饰
格式:
abstract class 类名{}
abstract void eat();
2、抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
抽象类里面可以有具体的实现方法
3、抽象类不能实例化
那么,抽象类如何实例化呢?
按照多态的方式,首先要有继承关系,由具体的子类实例化。
多态的形式实例化,我们在这里称之为:抽象类多态
4、抽象类的子类
1、如果是一个具体的子类,就必须重写所有的抽象方法
2、如果是一个抽象的子类,可以不重写父抽象类的抽象方法,也可以有选择性的重写
//由于类存在抽象方法,该类必须定义为抽象类
//class Demo{
// public abstract void show();
//}
abstract class Demo{
public abstract void show();
public void show2(){
System.out.println("这是在抽象类中的具体的方法");
}
}
//定义一个抽象类
abstract class Animal{
//定义一个抽象的方法,名字叫吃,没有方法体
public abstract void eat();
//下面这样定义抽象方法是错误的,{}代表空方法体,会报错,抽象方法不能有方法体
// public abstract void eat(){};
//定义一个抽象的方法,名字叫睡觉,没有方法体
public abstract void sleep();
}
//abstract class Demo2 extends Animal{
// @Override
// public void eat() {
// System.out.println("重写方法");
// }
//}
//快捷键 alt + enter
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("趴着睡");
}
}
public class AbstractDemo1 {
public static void main(String[] args) {
//Animal这个类是一个抽象类,而抽象类不能被实例化
// Animal animal = new Animal();
// Cat cat = new Cat();
// cat.eat();
// cat.sleep();
//用多态的形式进行实例化
Animal a1 = new Cat();
a1.eat();
a1.sleep();
}
}
抽象类中成员的特点:
成员变量:可以是变量,也可以是常量
构造方法:有构造方法
但是抽象类又不能被实例化,有个构造方法有什么用呢?
用于子类访问父类进行初始化
成员方法:
可以是具体的实现方法,也可也是抽象的方法
特点:
1、如果是一个具体的子类,就必须重写所有的抽象方法
2、如果是一个抽象的子类,可以不重写父抽象类的抽象方法,也可以有选择性的重写
abstract class Animal2{
int num = 20;
final int num2 = 200;
Animal2(){}
abstract public void sleep();
}
class Dog extends Animal2{
@Override
public void sleep() {
System.out.println("侧着睡");
}
}
public class AbstractDemo2 {
public static void main(String[] args) {
Animal2 a = new Dog();
a.sleep();
}
}
一个类如果没有抽象方法,可不可以定义为抽象类?
可以
如果可以,有什么意义?
如果说一大堆东西,他们都有共同的概念,这个共同的概念本身在现实中是没有具体的存在,把这些概念
集合起来归为一个类,这个类就是抽象类。
至于说这个抽象类有没有方法,却决于这一大堆东西有没有共同的行为,如果说他们只是有着相同的本质。
但是呢,没有共同的行为,这也是合情合理的。
总结:
1、抽象类里面可以没有抽象方法
2、抽象类不能被实例化
abstract不能和哪些关键字共存
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();
}
public class AbstractDemo3 {
public static void main(String[] args) {
}
}
抽象类练习1:
猫狗案例
具体事物:猫,狗
共性:姓名,年龄,吃饭
分析:从具体到抽象的过程
猫:
成员变量:姓名,年龄
构造方法:无参构造,有参构造
成员方法:吃饭(猫吃鱼)
狗:
成员变量:姓名,年龄
构造方法:无参构造,有参构造
成员方法:吃饭(狗吃肉)
通过分析发现,猫和狗有一些共性内容,所以我们就根据这些共性内容提取了一个父类:动物类:Animal
但是呢,又由于吃饭的方式不同,所以吃饭的方法我们定义为抽象方法。
又因为,吃饭的方法是一个抽象方法,所以该类必须定义为抽象类
抽象动物类:Animal
成员变量:姓名,年龄
构造方法:无参构造,有参构造
成员方法:吃饭,是一个抽象方法 eat();
实现:从抽象到具体
抽象动物类:Animal
成员变量:name,age;
构造方法:无参构造,有参构造
成员方法:吃饭,是一个抽象方法 public abstract void eat();
狗类:
继承自动物类
无参构造,有参构造
重写抽象的吃饭方法
猫类:
继承自动物类
无参构造,有参构造
重写抽象的吃饭方法
abstract class Animal3{
private String name;
private int age;
public Animal3() {
}
public Animal3(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//是一个抽象方法 public abstract void eat();
public abstract void eat();
}
class Dog3 extends Animal3{
public Dog3() {
}
public Dog3(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
class Cat3 extends Animal3{
public Cat3() {
}
public Cat3(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class AbstractTest {
public static void main(String[] args) {
Animal3 a = new Cat3("小花",3);
System.out.println(a.getName()+"---"+a.getAge());
a.eat();
Animal3 a2 = new Dog3("大黄",4);
System.out.println(a2.getName()+"---"+a2.getAge());
a2.eat();
}
}
老师案例
具体事物:十三期老师,十二期老师
共性:姓名,年龄,讲课。
分析:
十三期老师:
姓名,年龄
讲课(讲JavaSE)
十二期老师:
姓名,年龄
讲课(讲Hive)
实现:
抽象的老师类:
姓名,年龄
讲课,定义为抽象方法
十三期老师:
继承自老师类
姓名,年龄
讲课(讲JavaSE)
十二期老师:
继承自老师类
姓名,年龄
讲课(讲Hive)
abstract class Teacher{
private String name;
private int age;
public Teacher() {
}
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void teach();
}
class ThirteenTeacher extends Teacher{
public ThirteenTeacher() {
}
public ThirteenTeacher(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("教JavaSE");
}
}
class TwelveTeacher extends Teacher{
public TwelveTeacher() {
}
public TwelveTeacher(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("教Hive");
}
}
public class AbstractTest2 {
public static void main(String[] args) {
Teacher t1 = new ThirteenTeacher("小虎",24);
System.out.println(t1.getName()+"---"+t1.getAge());
t1.teach();
Teacher t2 = new TwelveTeacher("火火",24);
System.out.println(t2.getName()+"---"+t2.getAge());
t2.teach();
}
}
学生案例
具体事务:十三期学员,十二期学员
共性:姓名,年龄,班级,学习,吃饭
分析:
十三期学员:
姓名,年龄,班级
学习(学习Java基础),吃饭
十二期学员:
姓名,年龄,班级
学习(学习Hive),吃饭
抽象的学员:
姓名,年龄,班级
学习(定义为抽象方法),吃饭
实现:
十三期学员:
姓名,年龄,班级
学习(学习Java基础),吃饭
十二期学员:
姓名,年龄,班级
学习(学习Hive),吃饭
抽象的学员:
姓名,年龄,班级
学习(定义为抽象方法),吃饭
abstract class Trainee{
private String name;
private int age;
private String clazz;
public Trainee() {
}
public Trainee(String name, int age, String clazz) {
this.name = name;
this.age = age;
this.clazz = clazz;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
//这是抽象的学习方法
public abstract void study();
//具体的吃米饭的方法
public void eat(){
System.out.println("吃米饭");
}
}
class ThirteenTrainee extends Trainee{
public ThirteenTrainee() {
}
public ThirteenTrainee(String name, int age, String clazz) {
super(name, age, clazz);
}
@Override
public void study() {
System.out.println("学习Java基础");
}
}
class TwelveTrainee extends Trainee{
public TwelveTrainee() {
}
public TwelveTrainee(String name, int age, String clazz) {
super(name, age, clazz);
}
@Override
public void study() {
System.out.println("学习Hive");
}
}
public class AbstractTest3 {
public static void main(String[] args) {
Trainee t1 = new ThirteenTrainee("陈俊荣",17,"十三期");
System.out.println(t1.getName()+"---"+t1.getAge()+"---"+t1.getClazz());
t1.study();
t1.eat();
Trainee t2 = new TwelveTrainee("航航",18,"十二期");
System.out.println(t2.getName()+"---"+t2.getAge()+"---"+t2.getClazz());
t2.study();
t2.eat();
}
}
假如我们在开发一个系统时需要对员工类进行设计,员工包含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();
}
}