继承
什么是继承?
当多个类中,有相同的成员的时候,可以把这些相同的成员抽取到另外一个类中,这个类我称之为父类(基类/超类),由父类生成的一个类,那么这个类叫子类(派生类)
建立继承关系后,有什么特点?
子类继承父类这后会自动拥有父类中可继承的成员,非私有的成员是无法继承的,子类还可以有特有的成员
继承的好处
提高了代码的
继承的格式
使用extends关键字让类与类之间产生继承的关系
继承格式:
// 定义父类
public class 父类{}
// 定义子类 继承父类
public class 子类 extends 父类{}
继承中成员变量的访问特点
直接使用:通过对象名调用成员变量;=左边是谁,用的就是谁的变量,没有则往上找
间接使用:通过定义方法的形式使用成员变量就看方法属于谁,用的就是谁,没有则网上找
public class Fu {
int num =5;
}
public class Zi extends Fu {
int num2 = 6;
public void show(){
//父类与子类的成员变量不同,如果相同则使用调用父类成员变量使用super关键字
//使用子类成员变量使用this关键
System.out.println("fu num="+num);
System.out.println("zi num2="+num2);
}
}
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
zi.show();
}
}
区分子类方法中重名的三种变量
访问局部变量:直接使用
访问子类成员变量:this.成员变量
访问父类成员变量:super.成员变量
public class Fu {
int num= 5;
}
public class Zi extends Fu {
int num = 8;
public void show(){
System.out.println("fu num="+super.num);
System.out.println("zi num="+this.num);
}
}
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
zi.show();
}
}
继承中成员方法的访问特点
子类的,可以简单理解为就近原则
public class Fu {
public void show(){
System.out.println("fu类中的show方法执行");
}
}
public class Zi extends Fu{
public void show2(){
System.out.println("zi类中的show方法执行");
}
}
public class test {
public static void main(String[] args) {
Zi zi = new Zi();
zi.show2();//调用子类方法
zi.show();//调用父类方法
//父子类成员方法不同,如果相同,则称为重写Override,子类声明对象则调用子类成员方法
}
}
重写和重载的概念
重载:overload
在同一个类中,方法名相同,参数列表,与返回值无关和修饰符也无关
参数列表不同:
参数的个数不同,如果参数个数相同,与之对应数据类型不同
重写(覆盖,覆写):override
必须是在子父继承关系中或接口关系中,才有重写的概述,子类的方法与父类中方法的方法一模一样,就诶形成了方法的重写。
继承中方法的覆盖重写注意事项
- 子类的权限必须要大于等于父类的权限(public protected default private)
- 子类的返回值必须是小于等于父类的范围
- 要想保证有效的重写,在类上加上一个注解即可
方法重写的使用场景
当父类的功能无法满足子类需求时,这个时候需要在子类覆盖重写父类的功能
好处是:子类既有了新的功能,又保持了父类原有的功能
如果想使用父类原有的功能,使用super.父类方法名(参数列表);
构造方法可以继承吗
不可以,每一个类的构造方法必须跟当前类的名称一致,再有就是,构造方法的作用就是给类中成员进行赋值的。
访问构造方法的注意事项
- 在子类构造方法的第一行,默认有super(),默认了父类的无参构造
- 如果想动手调用父类的其他有参构造,在子类构造方法中的第一行:super(无参列表);
- 一旦手动调用父类的其他无参构造,默认的super()将不再给出。
public class Fu {
private int n;
Fu(){
System.out.println("fu()");
}
}
public class Zi extends Fu {
Zi(){
//调用父类的构造方法
super();
System.out.println("zi()");
}
}
public class Test {
public static void main(String[] args) {
/**
* 在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空
*
* 间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构
*
* 造方法调用时,一定先调用父类的构造方法。
*/
Zi zi = new Zi();
}
}
this关键字的三中用法
- 成员变量 this.成员变量
- 成员方法 this.成员方法(参数列表)
- 构造方法 this(参数列表)
this和super它们两个必须是在构造方法中的第一行。也就是说,有this没有super,有super没有this
抽象类
什么是抽象类
抽象方法所在的类必定是一个抽象类。抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
声明抽象方法会造成以下两个结果:
如果一个类包含抽象方法,那么该类必须是抽象类。
任何子类必须重写父类的抽象方法,或者声明自身为抽象类。继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。
最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
抽象类和普通类的父类有什么区别?
抽象类父类:可以有抽象方法和非抽象方法,但不可以创建对象
普通父类:有非抽象成员方法,可以创建对象
成员变量
抽象类:有成员变量
普通类:有成员变量
成员方法
抽象类:有抽象方法,也有非抽象方法
普通类:只能是普通成员方法
抽象方法定义格式
//1.抽象方法定义格式
public abstract 返回值 方法名(参数列表);
//2.抽象类定义格式
public abstract class 类名{}
抽象方法和抽象类的注意事项
- 抽象类是不能创建实例对象的
- 抽象类有抽象方法,也可以有非抽象方法(作用就是抽取多个类的共有的内容,达到复用作用)
- 子类继承了抽象类,必须是要重写它所有的抽象方法
- 抽象类也是可以有构造方法的,给子类调用的,目的是给抽象类中的数据初始化
- 子类继承了抽象类,必须是要重写它所有的抽象方法,否则这个类是一个抽象类
继承,抽象类,抽象方法,方法重写等案例
1.定义抽象类 Employee 表示职员 包含受保护的属性:姓名,基本工资,家庭住址,该月休假数;为Employee类提供构造函数,为每个属性赋值; 编写show()方法显示所有信息;编写方法:calculateLessPay() 计算扣除 规则为无休假不扣除,5天以内(包含5天)扣除基本工资的4分之1,超过5天扣除基本工资的一半。 编写抽象方法calculateTotal()计算工资总额。2.编写子类Director 表示董事长 包含私有属性transportAllowance 表示交通补助 给该类提供构造函数,给每个属性赋值,注意使用super 重写calculateTotal()方法计算董事长的工资总额,计算标准为: 基本工资+岗位津贴5000+交通补助 重写show()方法显示基本信息,并显示董事长的总工资和实际工资(总工资-应扣工资)3.编写子类 Manager 表示部门经理 类中包含私有属性:Department 表示部门 给该类提供构造函数,给每个属性赋值,注意使用super 重写calculateTotal()方法计算部门经理的工资总额,计算标准为: 基本工资+岗位津贴1500+绩效工资:基本工资的20%。 重写show()方法,显示基本信息,所在部门名称,以及总工资与实际工资(总工资-应扣工资)
代码:
Employee抽象类
package 抽象类.demo04;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/10 15:55
*/
public abstract class Employee {
/**
* 1.定义抽象类 Employee 表示职员
* 包含受保护的属性:姓名,基本工资,家庭住址,该月休假数;为Employee类提供构造函数,为每个属性赋值;
* 编写show()方法显示所有信息;编写方法:calculateLessPay() 计算扣除
* 规则为无休假不扣除,5天以内(包含5天)扣除基本工资的4分之1,超过5天扣除基本工资的一半。
* 编写抽象方法calculateTotal()计算工资总额。
*/
//董事长岗位津贴
public final int jobSubsidiesDiretor = 5000;
//部门经理岗位津贴
public final int jobSubsidiesManager = 1500;
private String name;//姓名
private double salary;//基本工资
private String address;//地址
private int restDay;//休息天数
/**
* 显示所有信息
*/
public void show(){
System.out.print("姓名:"+this.name+"\t家庭住址:"+this.address+"\t该月休假数:"+this.restDay+"\t总工资:"+this.salary+"\t");
calculateTotal();
System.out.println();
}
/**
* 工资扣除
* @param newSalary
* @return
*/
public double calculateLessPay(double newSalary){
if (restDay <= 0){
newSalary=salary;
}else if (restDay>0 && restDay<=5){
newSalary=(salary*0.25);
}else if (restDay>5){
newSalary=(salary*0.5);
}
return newSalary;
}
/**
* 工资计算抽象方法
*/
public abstract void calculateTotal();
/**
* 空参有参构造
*/
public Employee(){}
public Employee(String name, double salary, String address, int restDay) {
this.name = name;
this.salary = salary;
this.address = address;
this.restDay = restDay;
}
//getter和setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getRestDay() {
return restDay;
}
public void setRestDay(int restDay) {
this.restDay = restDay;
}
}
Director实现类
package 抽象类.demo04;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/10 16:33
*/
/**
* 2.编写子类Director 表示董事长
* 包含私有属性transportAllowance 表示交通补助
* 给该类提供构造函数,给每个属性赋值,注意使用super
* 重写calculateTotal()方法计算董事长的工资总额,计算标准为:
* 基本工资+岗位津贴5000+交通补助
* 重写show()方法显示基本信息,并显示董事长的总工资和实际工资(总工资-应扣工资)
*/
public class Director extends Employee{
private double transportAllowance;//交通补助
/**
* 实现工资计算抽象方法
*/
@Override
public void calculateTotal() {
double directorSalary = getSalary()+transportAllowance+jobSubsidiesDiretor-calculateLessPay(getRestDay());
System.out.print("扣除后工资:"+directorSalary);
}
/**
* 重写show方法
*/
@Override
public void show() {
System.out.print("姓名:"+getName()+"\t家庭住址:"+getAddress()+"\t该月休假数:"+getRestDay()+"\t总工资:"+getSalary()+"\t");
calculateTotal();
System.out.println();
}
//空参有参构造
public Director(){}
public Director(String name, double salary, String address, int restDay, double transportAllowance) {
super(name, salary, address, restDay);
this.transportAllowance = transportAllowance;
}
//getter和setter方法
public double getTransportAllowance() {
return transportAllowance;
}
public void setTransportAllowance(double transportAllowance) {
this.transportAllowance = transportAllowance;
}
}
Manager实现类
package 抽象类.demo04;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/10 16:52
*/
public class Manager extends Employee{
/**
* 3.编写子类 Manager 表示部门经理
* 类中包含私有属性:Department 表示部门
* 给该类提供构造函数,给每个属性赋值,注意使用super
* 重写calculateTotal()方法计算部门经理的工资总额,计算标准为:
* 基本工资+岗位津贴1500+绩效工资:基本工资的20%。
* 重写show()方法,显示基本信息,所在部门名称,以及总工资与实际工资(总工资-应扣工资)
*/
private String department;//部门
/**
* 重写工资计算抽象方法
*/
@Override
public void calculateTotal() {
double directorSalary = getSalary()*(1.2)+jobSubsidiesManager-calculateLessPay(getRestDay());
System.out.print("扣除后工资:"+directorSalary);
}
/**
* 重写show方法
*/
@Override
public void show() {
System.out.print("姓名:"+getName()+"\t所在部门:"+getDepartment()+"\t家庭住址:"+getAddress()+"\t该月休假数:"+getRestDay()+"\t总工资:"+getSalary()+"\t");
calculateTotal();
System.out.println();
}
//有参无参构造
public Manager(){}
public Manager(String name, double salary, String address, int restDay, String department) {
super(name, salary, address, restDay);
this.department = department;
}
//getter和setter方法
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
员工类Staff类
package 抽象类.demo04;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/10 16:06
*/
public class Staff extends Employee {
/**
* 实现工资计算抽象方法
*/
@Override
public void calculateTotal() {
double result = getSalary() - calculateLessPay(getRestDay());
System.out.print("扣除后工资:"+result);
}
}
测试类Test
package 抽象类.demo04;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/10 16:11
*/
public class Test {
public static void main(String[] args) {
Staff staff = new Staff();
staff.setName("小明");
staff.setAddress("北京");
staff.setRestDay(4);
staff.setSalary(8000);
staff.show();
// staff.calculateTotal();
//董事长
Director director = new Director();
director.setName("liFly");
director.setAddress("郑州");
director.setSalary(50000);
director.setRestDay(2);
director.setTransportAllowance(5000);
director.show();
// staff.calculateTotal();
Manager manager = new Manager();
manager.setName("小白");
manager.setAddress("郑州");
manager.setSalary(8000);
manager.setRestDay(3);
manager.setDepartment("研发部");
manager.show();
}
}
测试结果: