Day 6 面向对象的三大特征
封装
封装的必要性:在对象的外部,对对象的属性进行赋值,可能存在非法数据的录入。就目前的技术而言,并没有办法对属性的赋值加以控制。
概念:尽可能隐藏对象的内部实现细节,控制对象的修改及访问权限。
访问修饰符:private (可将属性修饰为私有,仅本类可见)
提供公共访问方法,以保证数据的正常录入,并在公共的访问方法内部,添加逻辑判断,进而过滤掉非法数据,以保证数据安全。
get/set方法是外界访问对象私有属性的唯一通道,方法内部可对数据进行检测和过滤。
继承
程序中的继承,是类与类之间特征和行为的一种赠与或获得。
两个类之间的继承关系,必须满足“is a”的关系。
语法:class 子类 extends 父类{ } //定义子类时,显示继承父类
应用:产生继承关系之后,子类可以使用父类中的属性和方法,也可定义子类独有的属性和方法。
优点:既提高代码的复用性,又提高代码的可扩展性。
不可继承
构造方法:
类中的构造方法,只负责创建本类对象,不可继承。
Private修饰的属性和方法:
访问修饰符的一种,仅本类可见。
父子类不再同一个包当中时,default修饰的属性和方法:
访问修饰符的一种,仅同包可见。
访问修饰符
本类 | 同包 | 非同包子类 | 其他 |
---|---|---|---|
private | √ | × | × |
default | √ | √ | × |
protected | √ | √ | √ |
public | √ | √ | √ |
方法的覆盖
当父类提供的方法无法满足子类需求时,可在子类中定义和父类相同的方法进行覆盖。
方法覆盖原则:
方法名称、参数列表、返回值类型必须与父类相同。
访问修饰符可与父类相同或是比父类更宽泛。
方法覆盖的执行:
子类覆盖父类方法之后,调用时优先执行子类覆盖后的方法。
super关键字
在子类中,可直接访问从父类继承到的属性和方法,但如果父子类的属性或方法存在重名(属性遮蔽、方法覆盖)时,需要加以区分,才可专项访问。
super访问方法
super关键字可在子类中访问父类方法。
使用“super . ”的形式访问父类方法,进而完成在子类中的复用,再叠加额外的功能代码,组成新的功能。
父子类的同名属性不存在覆盖关系,两块空间同时存在(子类遮蔽父类属性),需使用不同前缀进行访问。
继承中的对象创建
在具有继承关系的对象创建中,构建子类对象会==先==构建父类对象。
由父类的共性内容,叠加子类的独有内容,组合成完整的子类对象。
super调用父类构造方法
super():表示调用父类无参构造方法。如果没有显示书写,隐式存在于子类构造方法的首行。
super(实参):表示调用父类有参构造方法。
小结:
一个类只能有一个直接父类,但可以多级继承,属性和方法逐级叠加。
super关键字的两种用法:
在子类方法中使用“super . ”的形式访问父类的属性和方法。
在子类的构造方法的首行,使用“super()”或“super(实参)”,调用父类构造方法。
注意:
如果子类构造方法中,没有显示定义super()或super(实参),则默认提供super()。
同一个子类构造方法中,super()、this()不可同时存在。
多态
概念:父类引用指向子类对象,从而产生多种形态。
二者具有直接或间接的继承关系时,父类引用可指向子类对象,即形成多态。
父类引用仅可调用父类所声明的属性和方法,不可调用子类独有的属性和方法。
多态的应用
场景一:使用父类作为方法形参实现多态,使方法参数的类型更为宽泛。
场景二:使用父类作为方法返回值实现多态,使方法可以返回不同子类对象。
向上转型(装箱)
父类引用中保存真是子类对象,称为向上转型(即多态核心概念)
注意:仅可调用Animal中所声明的属性和方法。
向下转型(拆箱)
将父类引用中的真实子类对象,强制转回子类本身类型,称为向下转型。
注意:只有转换回子类真实类型,才可调用子类独有的属性和方法。
instanceOf 关键字
向下转型前,应判断引用中的对象真实类型,保证类型转换的正确性。
语法:引用 instanceOf 类型 //返回boolean类型结果
多态的作用
1.屏蔽子类间的差异
2.灵活、耦合度低
综合案例
class Employee{
private String name;
private int month;
public double getSalary(int month){
if(this.month == month){
return 100.0;
}else{
return 0.0;
}
}
public Employee(){}
public Employee(String name,int month){
this.name = name;
this.month = month;
}
public int getMonth(){
return month;
}
}
class SalariedEmployee extends Employee{
private double salary;
public SalariedEmployee(){}
public SalariedEmployee(String name,int month,double salary){
super(name,month);
this.salary = salary;
}
public double getSalary(int month){
if(super.getMonth() == month){ //super关键字用法
return 100.0+this.salary;
}else{
return 0.0+this.salary;
}
}
}
class HourlyEmployee extends Employee{
private double hourlySalary;
private int hours;
public HourlyEmployee(){}
public HourlyEmployee(String name,int month,double hourlySalary,int hours){
super(name,month);
this.hourlySalary = hourlySalary;
this.hours = hours;
}
public double getSalary(int month){
if(super.getMonth() == month){
if(hours > 160){
return 100.0+hours*hourlySalary+(hours-160)*(0.5*hourlySalary);
}else{
return 100.0+hours*hourlySalary;
}
}else{
if(hours > 160){
return 0.0+hours*hourlySalary+(hours-160)*(0.5*hourlySalary);
}else{
return 0.0+hours*hourlySalary;
}
}
}
}
class SalesEmployee extends Employee{
private double sales;
private double rate;
public SalesEmployee(){}
public SalesEmployee(String name,int month,double sales,double rate){
super(name,month);
this.sales = sales;
this.rate = rate;
}
public double getSalary(int month){
if(super.getMonth() == month){
return 100.0+sales*rate;
}else{
return 0.0+sales*rate;
}
}
}
class BasePlusSalesEmployee extends SalesEmployee{
private double baseSalary;
public BasePlusSalesEmployee(){}
public BasePlusSalesEmployee(String name,int month,double sales,double rate,double baseSalary){
super(name,month,sales,rate); //super关键字用法2
this.baseSalary = baseSalary;
}
public double getSalary(int month){
return baseSalary+super.getSalary(month);
}
}
public class TestEmployee{
public static void main(String[] args) {
Employee[] employee = new Employee[4];
employee[0] = new SalariedEmployee("tom",3,2000);
employee[1] = new HourlyEmployee("tom",3,100,10);
employee[2] = new SalesEmployee("tom",3,10000,0.1);
employee[3] = new BasePlusSalesEmployee("tom",3,10000,0.1,1000);
for(int i = 0;i < 4;i++){
if(employee[i] instanceof BasePlusSalesEmployee){ //instanceOf 判断类型
System.out.println(((BasePlusSalesEmployee)employee[i]).getSalary(3)); //强制下转型
}else if(employee[i] instanceof SalesEmployee){
System.out.println(((SalesEmployee)employee[i]).getSalary(3));
}else if(employee[i] instanceof HourlyEmployee){
System.out.println(((HourlyEmployee)employee[i]).getSalary(3));
}else if(employee[i] instanceof SalariedEmployee){
System.out.println(((SalariedEmployee)employee[i]).getSalary(3));
}
}
}
}