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类,包括基本类型数组和对象数组

 

  

posted @ 2022-03-03 21:08  天空之城906  阅读(43)  评论(0)    收藏  举报