目录
抽象类
包含 有抽象方法的类 或 被abstract修饰的类
引入抽象类会有一个强制约束力,子类方法必须覆盖
抽象类和抽象方法必须用abstract关键字修饰
abstract class 类名{ } //不能 new 类名
public abstract void eat(); //没有方法体
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
抽象类不能直接实例化(创建对象)
抽象类的子类可以是抽象类,也可以是具体类
间接实例化:抽象类类型 引用 = new 具体子类();
package com.wolf.basic;
public class Demo1 {
public static void main(String[] args) {
Animal animal = new Cat();
animal.eat();
}
}
/*为了实现多态,不然编译看左面就没有方法*/
abstract class Animal {
public abstract void eat();
}
/*抽象类的子类是具体类*/
class Cat extends Animal {
@Override
public void eat() {
System.out.println("鱼");
}
public void sleep() {
System.out.println("睡了");
}
}
/*抽象类的子类是抽象类*/
abstract class MamalAnimal extends Animal {
//哺乳动物还是包含许多动物,还是没有具体实现
}
/*抽象类不一定有抽象方法*/
abstract class A {
public void Test() {
}
}
抽象类 vS 普通类 的成员特点:
构造方法:抽象类同普通类(不能实例化,为啥有构造方法?)
成员变量:抽象类同普通类
成员方法:
抽象类:
可以是抽象方法:类中有这样的行为,但不知如何实现
也可以是非抽象方法:主要实现代码复用
普通类:非抽象方法
不能实例化,为啥有构造方法?
1.因为抽象类中,可以像普通类一样,定义成员变量,而这些成员变量,在创建子类对象的时候,也是初始化
2.在子类对象当中,抽象父类中定义的成员,它们值的初始化,交给抽象父类的构造方法来完成(各司其职)
package com.wolf.basic;
/**
* @create 2021-07-25 18:59
* 不能实例化,为啥有构造方法?
*/
public class Demo2 {
}
abstract class Father {
int fatherI;
public Father(int fatherI) {
this.fatherI = fatherI;
}
}
class Son extends Father {
int sonI;
public Son(int fatherI, int sonI) {
super(fatherI);
this.sonI = sonI;
}
}
练习
假如我们在开发一个系统时需要对员工类进行设计:
1.员工包含3个属性:姓名、工号以及工资。
2.经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。
3.经理和员工,他们都有共同的行为,即工作,但是他们具体的工作内容背定不一样
请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。
package com.wolf.basic;
/**
* @create 2021-07-25 19:32
*/
public class Exercise {
public static void main(String[] args) {
Employee employee = new Employee("张三", 1, 100);
System.out.println(employee.getName() + " " + employee.getWorkId() + " " + employee.getSalary());
employee.work();
Manager manager = new Manager("Lisi", 2, 300, 100);
System.out.println(manager.getName() + " " + manager.getWorkId() + " " + manager.getSalary());
manager.work();
}
}
abstract class BaseEmployee {
private String name;
private int workId;
private double salary;
public BaseEmployee(String name, int workId, double salary) {
this.name = name;
this.workId = workId;
this.salary = salary;
}
//员工、经理都要工作,但内容不同
public abstract void work();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWorkId() {
return workId;
}
public void setWorkId(int workId) {
this.workId = workId;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
/*员工类*/
class Employee extends BaseEmployee {
public Employee(String name, int workId, double salary) {
super(name, workId, salary);
}
@Override
public void work() {
System.out.println("员工工作");
}
}
/*经理类*/
class Manager extends BaseEmployee {
public Manager(String name, int workId, double salary, double bonus) {
super(name, workId, salary);
this.bonus = bonus;
}
private double bonus;
@Override
public void work() {
System.out.println("经理工作");
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@Override
public double getSalary() {
return super.getSalary() + bonus;
}
}
1.抽象类中,可以不包含抽象方法,一个不包含抽象发发的抽象类的意义
虽不包含抽象方法,但无法直接new,对于绝大部分普通场景可以直接使用,可能在某些场景不能使用,让别人继承使用,写注释提示别人哪些场景适用(理论上)
2.abstract不能和哪些关键字共存
private 不可以
final 不可以
static 不可以
对于冲突的理解:对于抽象方法,要在代码中使用,必须依赖多态,调用子类中覆盖实现抽象父类的抽象方法,而被private、final、static关键字修饰的方法,都不能在子类中被覆盖
接口
不同动物的相同行为 放在一起 如果有的猫和狗可以跳或者计算,有的却不可以
package com.wolf.introduction;
/**
* @create 2021-07-25 20:53
*/
public class Demo1 {
public static void main(String[] args) {
Animal animal = new Cat();
animal.eat();
}
}
abstract class Animal {
public abstract void eat();
public abstract void shout();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("鱼");
}
@Override
public void shout() {
System.out.println("喵喵喵");
}
public void sleep() {
System.out.println("睡了");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("骨头");
}
@Override
public void shout() {
System.out.println("汪汪汪");
}
}
//此时可能会想到
abstract class SpecialAnimal {
public abstract void jump();//某些可以跳
public abstract void calculate();//某些可以计算
}
//类的单重继承不可以这么做,故引入接口
//class SpecialCat extends SpecialAnimal,Cat{}
interface SpecialAnimal {
public abstract void jump();//某些可以跳
public abstract void calculate();//某些可以计算
}
接口的语法
(接口是纯粹的抽象,抽象类可以都是普通类)
1.接口用关键字interface表示
格式: interface 接口名 { }
2.在Java语言中Interface也可以表示一种数据类型
a.类和接口都可以用来表示数据类型(类和接口是地位对等的),只不过他们的侧重点不一样
操作(行为)描述:
b.类定义的是一个数据集合 基于这个数据集的一组操作(行为),类所描述的这一组行为,它们是有关系的(间接),都可以访问同一个数据集合
c.接口表示数据类型,侧重于描述,一组具有特殊功能的行为,这些行为,可以完全没有任何关系。
接口中的方法,它们的关系比较的松散
3.类实现接口用implements表示
类和接口可以有实现关系(也可以说是继承关系),用implements表示
格式: class 类名 implements 接口名 {}
4.接口不能直接实例化(只能有抽象方法,jdk8及以后不是)
5.接口的子类:
a.可以是抽象类
b.也可以是具体类
public class Demo1 {
public static void main(String[] args) {
//接口的间接实例化
InterfaceClass interfaceClass = new InterfaceClass();
}
}
//定义一个接口
interface MyInterface{
public abstract void show();
}
//实现接口
class InterfaceClass implements MyInterface{
@Override
public void show() {
System.out.println("实例化");
}
}
接口的特点
无构造方法 成员变量:只能是常量,默认修饰符 public static final 成员方法:只能是抽象方法,默认修饰符 public abstract
回顾一下,之前我们讲类的时候说过,Java中类与类之间只能单重继承。那么是不是Java中,只有单重继承呢? 不是
之所以,java声称自己实现了多重继承
1.接口 与 接口 之间可以实现多重继承
2.一个类可以在继承其他类的情况下,同时实现多个接口
一个考虑接口的比较完整的类定义语法
class 类名 extends 其他类类名 implements接口1,接口2... { }
public class Demo3 {
}
interface FirstInterface {
void firstMethod();
}
interface SecondInterface {
void secondMethod();
}
interface ThirdInterface extends FirstInterface, SecondInterface {
}
class TestInterfaceExtend implements ThirdInterface {
@Override
public void firstMethod() {
}
@Override
public void secondMethod() {
}
}
interface FourthInterface {
void forthMethod();
}
interface FiveInterface {
void fiveMethod();
}
class CompleteClass extends TestInterfaceExtend implements FourthInterface, FiveInterface {
@Override
public void forthMethod() {
}
@Override
public void fiveMethod() {
}
}
抽象类和接口的比较
成员区别
抽象类 变量;有抽象方法;非抽象方法
接口 常量;抽象方法
关系区别
类与类继承,单继承
类与接口实现,单实现,多实现
接口与接口继承,单继承,多继承
设计理念区别
抽象类 被继承体现的是: "is a”的关系。共性功能
接口 被实现体现的是: ”like a”的关系。扩展功能
/*
接上
*/
interface SpecialSkills {
public abstract void jump();//某些可以跳
public abstract void calculate();//某些可以计算
}
class SpecialCat extends Cat implements SpecialSkills{
@Override
public void jump() {
System.out.println("cat jump");
}
@Override
public void calculate() {
System.out.println("cat calculate");
}
}
class SpecialDog extends Dog implements SpecialSkills{
@Override
public void jump() {
System.out.println("dog jump");
}
@Override
public void calculate() {
System.out.println("dog calculate");
}
}
练习
教练和运动员案例
乒乓球运动员和篮球运动员。乒乓球教练和篮球教练。
为了出国交流,跟乒乓球相关的人员都需要学习英语。
请用所学知识:分析,这个案例中有哪些抽象类,哪些接口,哪些具体类。
乒乓球运动员
丽性: name,age,salary
行为: eat() , sleep(), train() , match()
乒乓球教练
属性: name,age,salary,bonus
行为: eat(), sleep() , teach()
足球运动员
属性: name,age,salary
行为: eat(), sleep(), train() , match()
足球教练
属性: name,age,salary, bonus
行为: eat() , sleep(), teach()
从共性:
1.所有的运动员和教练员 定义一个所有运动员和教练员都要继承公共父类 Human 普通
有相同的属性: name,age,salary
有相同的行为: eat() , sleep()
2.定义类来描述运动员和教练员
a.教练员和运动员 继承 Human
b.对于教练员而言:定义一个类 Coach 抽象类 extend Human
多了一个属性 bonus
多了一个行为:teach(),同时注意到不同类型的教练员,teach的内容不一样,抽象方法
c.对于运动员而言:定义一个类 Athlete 抽象类 extends Human
多了运动员特有的行为: train() , match()
但是,不同类型的有动员,但是训练和比赛的内容是不一样,train(),match()抽象方法
3.分别定义
乒乓球运动员:TableTennisAthlete extends Athlete,继承之后,事项 train(),match()
乒乓球教练:TableTennisCoach extends Coach,继承只需要实现 teach()
足球运动员:FootballAthlete extends Athlete,继承之后,事项 train(), match()
足球教练:FootballCoach extends Coach,继承只需要实现 teach()
4.功能扩展
implements SpecialSkills{ }
package com.wolf.introduction;
/**
* @create 2021-07-26 16:35
*/
public class Exercise {
public static void main(String[] args) {
TableTennisAthlete tableTennisAthlete = new TableTennisAthlete("张三", 20, 1000);
tableTennisAthlete.learnEnglish();
tableTennisAthlete.match();
tableTennisAthlete.train();
tableTennisAthlete.eat();
tableTennisAthlete.sleep();
tableTennisAthlete.setSalary(2000);
System.out.println(tableTennisAthlete.getName() + " " + tableTennisAthlete.getSalary() + " " + tableTennisAthlete.getAge());
System.out.println("--------------------------------");
TableTennisCoach tableTennisCoach = new TableTennisCoach("lisi", 30, 10000, 5000);
tableTennisCoach.learnEnglish();
tableTennisCoach.teach();
tableTennisCoach.setBonus(1000);
System.out.println(tableTennisCoach.getName() + " " + tableTennisCoach.getSalary());
tableTennisCoach.sleep();
}
}
class Human {
private String name;
private int age;
private int salary;
public void eat() {
System.out.println(name + "吃");
}
public void sleep() {
System.out.println(name + "睡");
}
public Human(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
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 int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
abstract class Coach extends Human {
private int bonus;
public abstract void teach();
public Coach(String name, int age, int salary, int bonus) {
super(name, age, salary);
this.bonus = bonus;
}
public int getBonus() {
return bonus;
}
public void setBonus(int bonus) {
this.bonus = bonus;
}
@Override
public int getSalary() {
return super.getSalary() + bonus;
}
}
abstract class Athlete extends Human {
public Athlete(String name, int age, int salary) {
super(name, age, salary);
}
public abstract void train();
public abstract void match();
}
interface SpecialSkills {
void learnEnglish();
}
class TableTennisAthlete extends Athlete implements SpecialSkills {
public TableTennisAthlete(String name, int age, int salary) {
super(name, age, salary);
}
@Override
public void train() {
System.out.println("乒乓球运动员:" + super.getName() + "训练");
}
@Override
public void match() {
System.out.println("乒乓球运动员:" + super.getName() + "比赛");
}
@Override
public void learnEnglish() {
System.out.println("乒乓球运动员:" + super.getName() + "学英语");
}
}
class TableTennisCoach extends Coach implements SpecialSkills {
public TableTennisCoach(String name, int age, int salary, int bonus) {
super(name, age, salary, bonus);
}
@Override
public void teach() {
System.out.println("乒乓球教练:" + super.getName() + "教课");
}
@Override
public void learnEnglish() {
System.out.println("乒乓球教练:" + super.getName() + "学习英语");
}
}
class FootballAthlete extends Athlete {
public FootballAthlete(String name, int age, int salary) {
super(name, age, salary);
}
@Override
public void train() {
System.out.println("足球运动员:" + super.getName() + "训练");
}
@Override
public void match() {
System.out.println("足球运动员:" + super.getName() + "比赛");
}
}
class FootballCoach extends Coach {
public FootballCoach(String name, int age, int salary, int bonus) {
super(name, age, salary, bonus);
}
@Override
public void teach() {
System.out.println("足球教练:" + super.getName() + "教课");
}
}