抽象类的特点:
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(); } }