抽象类
引入
我们常常所说的猫,狗,猪,熊猫,老虎等等都是动物具体的例子,而动物本身是一个抽象的概念,并且动物中吃的方法应该也不是一个具体的实现,以及所有动物共同拥有的方法在动物中应该都是抽象的表现,我们把一个不具体的功能,叫做抽象方法,而如果一个类中有抽象方法,我们就把这个类称之为抽象类。
特点
1、抽象类和抽象方法都要用一个关键字修饰:abstract
修饰一个类 放在class的前面
举例: abstract class Animal3{}
修饰一个方法 一般是放在权限修饰符后面
定义一个抽象的show方法
举例:public abstract void show();
抽象方法没有方法体{},连大括号都没有,直接以分号结尾
2、有抽象方法的类一定要是抽象类,抽象类不一定要有抽象方法,具体的类中不能有抽象方法,抽象类中既可以存在抽象方法,也可以存在有方法体的方法。
3、抽象类不能被实例化(不能被创建对象)
既然不能被实例化,那写在抽象类中的方法如何被调用呢?
抽象类如何创建呢?
通过多态的形式,使用具体的子类去实例化调用方法,专业术语称之为:抽象多态
4、如果继承 抽象类的是一个具体的子类,需要重写该抽象类中所有的抽象方法,如果继承抽象类的也是一个抽象类,可以不去重写父类中的抽象方法,也可以选择性的去重写。
成员的特点
成员变量:
既可以是变量,也可以是常量
构造方法:
可以存在构造方法,但抽象类不能被实例化,这里构造方法意义是什么?
要想初始化子类,必须先初始化父类,所以这里构造方法是提供初始化父类的作用
成员方法:
可以是抽象方法,但是具体的子类必须要重写该方法
也可以不是抽象方法,提高代码的复用性。
抽象类改进猫狗案例
abstract class Animal5{
//定义一个吃饭的抽象方法,不给出具体的实现
public abstract void eat();
//定义一个睡觉的抽象方法,不给出具体的实现
public abstract void sleep();
}
//alt+enter
class Dog5 extends Animal5{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
}
class Cat5 extends Animal5{
@Override
public void eat() {
System.out.println("猫吃🐟");
}
@Override
public void sleep() {
System.out.println("🐱趴着睡");
}
}
public class AbstractTest1 {
public static void main(String[] args) {
//抽象多态创建一个对象
Animal5 a = new Dog5();
a.eat();
a.sleep();
//抽象多态创建第二个对象
Animal5 c = new Cat5();
c.eat();
c.sleep();
}
}
用抽象类改进员工类
/*
假如我们在开发一个系统时需要对员工类进行设计,员工包含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 CommonStaff extends Staff{
public CommonStaff() {
}
public CommonStaff(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(int bonus) {
this.bonus = bonus;
}
public Manager(String name, String id, int salary, int bonus) {
super(name, id, salary);
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("做PPT");
}
}
public class AbstractTest4 {
public static void main(String[] args) {
//创建第一个对象
Staff s1 = new CommonStaff("小虎","KZ0080",100000);
s1.work();
//创建第二个对象
Staff s2 = new Manager("小周","SJ00030",200000,1000000);
s2.work();
}
}
疑问:
1、一个类如果没有抽象方法,可不可以定义为抽象类?
可以
2、如果可以,有什么意义?
橙汁,水,牛奶这些东西都拥有共同的特点,都是液体。我们把这些相同的行为概念归结成一个类,假设就叫做液体。
至于后面有没有抽象方法,取决于这些东西有没有相同的功能,只是说有着相同的本质,没有实际相同的行为,我们只定义一个抽象类,不写抽象方法,也是可以的。
3、抽象类中可以存在哪些关键字?
abstract关键字不能和哪些关键字共存?
1、abstract可以和public关键字共存
public abstract void show();
2、private和abstract关键字冲突
// private abstract void show2(); // java: 非法的修饰符组合: abstract和private
3、static和abstract关键字冲突
// static abstract void show3(); // java: 非法的修饰符组合: abstract和static
4、final和abstract关键字冲突
// final abstract void show4(); // java: 非法的修饰符组合: abstract和final
接口
1、语句定义格式
接口使用关键字:interface表示
interface 接口名{}
2、如何实现接口
接口不能直接实例化
1、使用多态的形式进行实现,由具体的子类进行实例化,其实这是多态的一种,叫做接口多态。
2、也可以用一个抽象类去实现
代码示例(将猫狗案例加入钻火圈的功能改写):
abstract class Animal{
private String name;
private int age;
public Animal() {
}
public Animal(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();
}
class Cat extends Animal{
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("🐱吃🐟");
}
}
//定义一个钻火圈的接口
interface ZuanHuoQuan{
void zuanHuo();
}
class TrainCat extends Cat implements ZuanHuoQuan{
@Override
public void zuanHuo() {
System.out.println("猫钻火圈");
}
}
public class InterfaceDemo1 {
public static void main(String[] args) {
// ThainSkill thainSkill = new ThainSkill();
// ThainSkill ts = new Demo();
//定义出了一个会钻火圈的猫
Cat c = new TrainCat();
// c.zuanHuo();
TrainCat tc = (TrainCat) c;
tc.zuanHuo();
}
}
3、接口中成员的特点
成员变量:
只能是常量,并且是静态的
JVM在真正运行之前会自动补齐修饰符:public static final
建议:在学习阶段手动补齐,在开发阶段,省略不写。
构造方法:
接口中没有构造方法。
成员方法:
接口中的方法只能是抽象方法,没有方法体,连大括号都没有
JVM在真正运行之前会自动补齐修饰符:public abstract
建议:在学习阶段手动补齐,在开发阶段,省略不写。
注意:
1、当一个具体的类实现接口的时候,必须实现接口中所有的抽象方法
2、当一个抽象类实现接口的时候,可以选择不实现接口中的方法,也可以选择性的实现
4、类与类,类与接口,接口与接口的关系
类与类:
存在继承关系,只能进行单继承,不可以进行多继承,但是可以是多层继承
类与接口:
实现关系,可以是单实现,也可以一次性实现多个接口,也可以在继承一个类的同时,实现多个接口
接口与接口:
存在的是继承关系,可以进行单继承,也可以进行多继承
interface Inter2{}
interface Inter3{}
interface Inter4 extends Inter2,Inter3{}
class Demo3 extends Object implements Inter2,Inter3{}
public class InterfaceDemo3 {
}