Java继承(一)
1、继承最明显的一个特征是“is-a”关系,什么什么是什么,比如经理是员工,员工是超类,经理是子类,用extends关键字表示
2、在设计继承关系的时候,通常把最一般的方法和变量放在超类中,比较特殊的方法和变量放在子类中,这是一种面向对象的编程思维
3、比如说现在有两个类Employee员工类,Manager经理类
public class Employee { private String name; private double salary; private LocalDate hireDay; public Employee(String name,double salary,int year,int month,int day){ this.name = name; this.salary = salary; hireDay = LocalDate.of(year,month,day); } public String getName() { return name; } public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public void raiseSalary(double byPercent){ double raise = salary * byPercent / 100; salary += raise; } }
public class Manager extends Employee {
private double bonus;
public void setBonus(double bonus) {
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public Manager(String name,double salary,int year,int month,int day){
super(name,salary,year,month,day);
bonus = 0;
}
@Override
public double getSalary() {
return super.getSalary() + bonus;
}
}
通过用extends继承关键词,Manager类除了自身的bonus属性外,还可以得到name、salary、hireDay三个属性,所以子类比超类拥有的功能更多
4、但是有时候超类的某些方法继承到子类中的时候,并不能满足于子类的需要,比如获取薪水的方法getSalary(),子类Manager还有个奖金bonus需要加进去,才是manager正确的薪水
所以这个时候我们子类要覆盖重写超类中的getSalary()方法
我们怎么获取到超类中私有的salary属性呢,那只有通过超类中的getSalary()公共方法获取,如果我们直接在子类的getSalary()方法中写getSalary(),那程序只会无限次的调用自己的getSalary(),直到程序崩 溃,这个时候我们引入一个super关键词,通过super.getSalary()就可以获得超类的salary属性了
记住super不是一个对象的引用,只是指示编译器调用超类方法的特殊关键词,和this的概念不一样
public Manager(String name,double salary,int year,int month,int day){ super(name,salary,year,month,day); bonus = 0; }
5、超类Employee类中的变量都是私有的,我们在子类中怎么提供一个构造器呢,这时可以利用supper()特殊语法,不过super调用构造器的语句必须在子类构造器的第一条
6、如果子类构造器没有显示的调用超类的构造器,将自动调用超类的无参构造器;如果超类中没有无参构造器,并且子类的构造器中又没有显式的调用超类的其他构造器,java编译器就会报错
7、this和super关键词的两层含义:
this:一是指示隐式参数的引用,二是调用该类的其他构造器
super:一是调用超类的方法,二是调用超类的构造器
8、在java语言中,对象变量是多态的
一个Employee类型的变量既可以引用一个Employee类型的对象,也可以引用Employee类的任何一个子类的对象
方法的名字和参数列表称为方法的签名,值得注意的是返回类型不是签名的一部分,不过我们在做覆盖重写的时候,一定要保证返回类型的兼容性:允许子类将覆盖方法的返回类型改为原返回类型的子类型
final类和方法
1、被final修饰的类是无法派生出子类的,换句话说就是你这个类如果不想被其他类继承,那就用final关键词进行修饰
如果将一个类声明为final的话,类里面的所有方法自动成为final方法,但字段变量不是,对于字段声明final,在构造对象之后就不允许改变它的值了
public final class Excutive extends Manager {}
2、如果超类中的某个方法不想被子类覆盖重写,那我们可以将这个方法声明为final
public final String getName(){}
将类和方法声明为final的一个最主要的原因是:确保它们不会在子类中改变语义,不允许其他类来捣乱;当然了,被final声明的类是不可能有子类的
final是类和方法洁身自好的重要保证,哈哈
强制类型转换
在引用类型的强制转换时遵循两条规则
1、只能在继承层次内进行强制类型转换
2、在将超类强制转换成子类之前,应该使用instanceof进行检查
抽象类
1、java中有继承的概念,所以引入抽象的概念是自然而然的事情
上面我们讲了,在设计超类的时候,要遵循更具有一般性普遍性;比如Employee是一个人,Student也是一个人,他们都有姓名name和对自身的一个描述description,于是就引出Person类,Person都 有姓名和描述,我们在给Person类的获取自身描述getDescription()方法做语义描述的时候,因为不知道是什么样的一个人,所以无法语义描述,这个时候我们可以用abstract关键字把Person类定义成 抽象类,抽象类中抽象方法起到了占坑的作用,这样就不用去具体实现getDescription()这个方法了
我们在Person中只定义这个方法,不去做实现,待继承Person的子类,通过覆盖重写Person的这个方法去做具体的实现就可以了
public abstract class Person { public abstract String getDescription(); }
2、如果子类Student在继承Person类的时候不覆盖实现这个方法的话,那么就要继续将Student类也定义为abstract抽象类
3、抽象类不能被实例化
4、可以用抽象类定义一个变量,但是这个变量只能引用非抽象子类的对象
Person p = new Student("name","description");
Object及其类型变量
1、Object类是所有类的始祖(超类),我们可以使用Object类型的变量引用任何类型的对象
Object obj = new Employee("Tom",60000);
2、在java中,只有基本类型不是对象,其他所有都扩展了Object类,包括基本类型数组和对象数组

浙公网安备 33010602011771号