继承的基本概念
什么是继承:继承就是可以直接使用前辈的属性和方法。
为什么需要继承:自然界中如果没有继承,那一切都是处于混沌状态,在软件开发中,我们可以借鉴自然界的机制,已经有的东西我们希望能够直接拿来用(复用)而不是重新开发。
如下面的示例:
定义人类:
public class Person {
private String id;//身份证号码
private String name ;//姓名
private String sex;//性别
//构造函数
public Person(String id, String name, String sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
public void print(){
System.out.println(id);
System.out.println(name);
System.out.println(sex);
}
}
定义员工类:
//员工类
public class Employee {
private String id;//身份证号码
private String name;//姓名
private String sex;//性别
private int salary;//工资
//系统生成构造函数
public Employee(String id, String name, String sex, int salary) {
this.id = id;
this.name = name;
this.sex = sex;
this.salary = salary;
}
public void print(){
System.out.println(id);
System.out.println(name);
System.out.println(sex);
System.out.println(salary);
}
}
测试类:
public class Test {
public static void main(String [] args){
Person p = new Person("410611199810216114","Chenanan","女");
Employee e = new Employee("4102215425523512","anan","男",360);
p.print();
e.print();
}
}
结果:
这样做的问题存在:1.重复劳动:人有姓名,性别等属性,员工中又重复定义了,将来可能在学生,教师等类中还要重复定义。2.信息不一致:比如人的性别用0-1表示,而员工类可能用“男/女”来表示,导致使用上的混乱。那么能否在员工类中使用已有人类的姓名,性别等,一一继承。
类的继承:
我们把上面的员工类改写以下,一一继承自person类
//员工类
public class Employee extends Person{
private int salary;//工资
public Employee(String id, String name, String sex, int salary) {
super(id, name, sex);
this.salary = salary;
}
//继承父类的输出方法
public void print(){
super.print();
System.out.println(salary);
}
}
使用继承很好的解决了上面提出的两个问题
extends 是“拓展,延伸”的含义,public class Employee extends Person就是声明一个叫做Employee的类,它是在Person类的基础上进行拓展,专业术语称之为继承自Person类
super是"超“的含义,person类相对于Employee类就是超类,通俗一点就是父类。
子类继承了父类的属性和方法,当然也可以在此基础上进行拓展-----加和改。在这个案例中加了”薪水“属性,改写了”打印“方法。这里有一个专业术语------重写(override)。
继承不仅仅解决了刚才的两个问题,还是得类有层次结构,逻辑上也更加合理。比如”员工“也是”人“。
多态
多态就是将同一个消息发送给不同对象是,他们所做的响应可能是不同的。比如说动物都有”叫“的方法,但是狗是”汪汪汪“的叫,而猫是”喵喵喵“的叫,当他们接收到被打的消息时,所做的响应是不同的。
案例:打动物
定义动物类,实现”叫“的方法
//动物类
public class Animal {
public void shout(){
System.out.println("吼吼···");
}
}
定义狗类,继承动物类,重写"叫”的方法
public class Dog extends Animal{
@Override
public void shout() {
System.out.println("汪汪···");
}
}
定义猫类,继承动物类,重写“叫”的方法
public class Cat extends Animal{
@Override
public void shout() {
System.out.println("喵喵···");
}
}
测试类
public class Test {
public static void main(String []args){
Dog d = new Dog();
Cat c = new Cat();
hit(d);
hit(c);
}
private static void hit(Dog d) {
d.shout();
}
private static void hit(Cat c) {
c.shout();
}
private static void hit(Animal a){
a.shout();
}
}
在测试程序中定义了一个“打”的方法,这种做法是比较笨拙的,有几种动物就需要定义几种方法,这个可能没完没了,有没有一劳永逸的方法?
不要传递Dog或者Cat等对象,而是传递一个Animal类对象就可以解决上面的问题。修改上面测试程序如下:
public class Test {
public static void main(String []args){
Dog d = new Dog();
Cat c = new Cat();
hit(d);
hit(c);
}
private static void hit(Animal a){
a.shout();
}
}
这里涉及了两个点:
1.赋值兼容性规则
hit方法型是Animal类型,而是实参是Dog或者Cat,所以类型不一致,为什么还可以呢?
所谓赋值兼容性规则,值得是凡是需要用到父类引用的父类引用的地方,都可以是用它的子类引用去代替。比如某人请求派车去接他,结果对方派了个三轮车去接了,虽然他可能不满意,但也没办法,因为对方是按照他的要求去做的。
2.多态
形参一定是父类的引用,而是参可以是他的任何一个子类的引用。