继承、多态及动态绑定

  1. 子类继承父类所有的属性和方法,但不能直接访问私有的属性和方法
  2. 子类必须要调用父类,才能完成父类的初始化
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况都会调用父类的无参构造器。如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定父类使用哪个构造器完成对父类的初始化工作,否则编译不会通过
  4. 如果希望指定父类的构造器,则显示调用一下:super()
  5. super()在使用时,必须放在构造器第一行
  6. super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器中
  7. java所有类都是Object的子类
  8. 父类构造器的调用不限于直接父类,将一直往上追溯到顶级父类Object
  9. java只支持单继承,如果要A继承B的同时又继承C,那只能让A继承B,B继承C
  10. 继承需满足 is-a 逻辑,例如 Cat extends Animal = > Cat is a Animal

继承原理

public class Son extends Father{
    String name = "小头儿子";

    public Son(){
        System.out.println(name+age+hobby);
    }

    public static void main(String[] args) {
        Son son = new Son();	//小头儿子39旅游
    }
}

class Father extends GrandPa{
    String name = "大头爸爸";
    int age = 39;
}

class GrandPa {
    String name = "大头爷爷";
    String hobby = "旅游";
    int age = 60;
}

在这里插入图片描述

  1. son对象初始化时,从自身开始,自下而上查找属性,直到Object对象

    查找name,存在
    查找age,不存在;则向Father类查找,存在
    查找hobby,不存在;则向Father类查找,不存在;则向Grander类查找,存在

  2. 不能越级查找

    比如将Father类的age访问修饰符设置为private,此时Son类已经不能获取Father的age属性了,但又不能越级查找GrandFa的age属性,因此会报错
    在这里插入图片描述

方法的多态

重载

方法名称相同,但参数类型或个数不同而状态不同。在编译期就进行绑定,属于静态绑定。以下是一个子类重载父类方法的例子

import java.util.HashMap;
import java.util.Map;

public class Demo1 {
    public static void main(String[] args) {
        Father father = new Son();
        father.convert(new HashMap());
    }
}

class Father{
    int age = 20;
    public void convert(Map map){
        System.out.println("父类被执行了");
        System.out.println(age);
    }
}

class Son extends Father{
    int age = 10;
    public void convert(HashMap hashMap){
        System.out.println("子类被执行了");
        System.out.println(age);
    }
}

最终输出是

父类被执行了
20

子类重载了父类的方法。在编译器阶段,father的引用类型是Father,因此编译期就已经绑定了father.convert方法调用的是Father类的convert方法。而属性没有重写之说,其值为编译期的值。

重写

建立在子类继承父类的基础上,方法名、参数类型、个数完全相同。

对象的多态

前提:两个类存在继关系

向上转型
本质:父类的引用指向了子类的对象
特点:
1. 可以调用父类的所有成员(需遵守访问规则)
2. 不可以调用子类的特有成员
3. 最终运行看子类的具体实现

instance of 比较操作符

判断对象的运行类型是否数xx类型或其子类型

public class Demo {
    public static void main(String[] args) {
        Father father = new Father();
        System.out.println(father instanceof Father);   //true  father的运行类型是否是Father类型或其子类型
        System.out.println(father instanceof Son);		//false	father的运行类型是否是Son类型或其子类型
        System.out.println(father instanceof GrandFa);	//true	father的运行类型是否是GrandFa类型或其子类型
    }
}

class GrandFa{
    int count = 10;
}
class Father extends GrandFa{
    int count = 5;
}
class Son extends Father{
    int count = 20;
}

综合例子

//测试Demo
//通过传入不同的对象,打印不同员工的工资和工作
public class PloyDemo {
    public static void main(String[] args) {
        Worker worker = new Worker("Tom", 2000);
        Manager manager = new Manager("Jack", 5000, 2000*12);
        showEmployeeAnnual(worker);
        showEmployeeAnnual(manager);
        testWork(worker);
        testWork(manager);
    }

    public static void showEmployeeAnnual(Employee employee){
        System.out.println(employee.getAnnual());
    }

    public static void testWork(Employee employee){
        if (employee instanceof Worker){
            ((Worker) employee).work();
        }else if (employee instanceof Manager){
            ((Manager) employee).manage();
        }
    }
}

//父类员工类
public class Employee {
    private String name;
    private int salary;

    public Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public int getAnnual(){
        return salary * 12;
    }
}

//子类普通员工
public class Worker extends Employee{

    public Worker(String name, int salary) {
        super(name, salary);
    }

    public void work(){
        System.out.println("普通员工" + this.getName() + "正在工作");
    }

    @Override
    public int getAnnual() {
        return super.getAnnual();
    }
}

//子类经理
public class Manager extends Employee{

    private int bonus;

    public Manager(String name, int salary, int bonus) {
        super(name, salary);
        this.bonus = bonus;
    }

    public int getBonus() {
        return bonus;
    }

    public void setBonus(int bonus) {
        this.bonus = bonus;
    }

    public void manage(){
        System.out.println("经理"+this.getName()+"管理员工");
    }

    @Override
    public int getAnnual() {
        return super.getAnnual() + bonus;
    }
}

动态绑定机制

  • 调用对象方法时,该方法会和该对象的内存地址/运行类型绑定,但在重载的情况下使用的是静态绑定
  • 当调用对象属性时,没有动态绑定机制,哪里声明哪里使用

例1. 均调用运行类型的方法

class A{
	public int i = 10;
	
	public int sum(){
		return getI() + 10;
	}
	
	public int sum1(){
		return i + 10;
	}
	
	public int getI(){
		return i;
	}
}

class B extends A{
	public int i = 20;
	
	public int sum(){
		return getI() + 20;
	}
	
	public int sum1(){
		return i + 10;
	}
	
	public int getI(){
		return i;
	}

	public static void main(String[] args){
		A a = new B();
		a.sum();	//40
		a.sum1();	//30	
	}
}

例2. 属性使用静态绑定,即编译期就确定值

B.sum()没找到
调用A.sum()
B中有getI(),调用B.getI(),i 没有动态绑定,用B.i

class A{
	public int i = 10;
	
	public int sum(){
		return getI() + 10;
	}
	
	public int sum1(){
		return i + 10;
	}
	
	public int getI(){
		return i;
	}
}

class B extends A{
	public int i = 20;
	
	//public int sum(){
	//	return getI() + 20;
	//}
	
	public int sum1(){
		return i + 10;
	}
	
	public int getI(){
		return i;
	}

	public static void main(String[] args){
		A a = new B();
		a.sum();	//30
		a.sum1();	//30	
	}
}

例3

调用B.sum1(),没找到
调用A.sum1(),用A.i

class A{
	public int i = 10;
	
	public int sum(){
		return getI() + 10;
	}
	
	public int sum1(){
		return i + 10;
	}
	
	public int getI(){
		return i;
	}
}

class B extends A{
	public int i = 20;
	
	public int sum(){
		return getI() + 20;
	}
	
	//public int sum1(){
	//	return i + 10;
	//}
	
	public int getI(){
		return i;
	}

	public static void main(String[] args){
		A a = new B();
		a.sum();	//40
		a.sum1();	//20	
	}
}
class A{
	public int i = 10;
	
	public int sum(){
		return getI() + 10;
	}
	
	public int sum1(){
		return i + 10;
	}
	
	public int getI(){
		return i;
	}
}

class B extends A{
	public int i = 20;
	
	public int sum(){
		return getI() + 20;
	}
	
	public int sum1(){
		return i + 10;
	}
	
	//public int getI(){
	//	return i;
	//}

	public static void main(String[] args){
		A a = new B();
		a.sum();	//30
		a.sum1();	//30	
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值