JAVA06 封装继承多态 总结(初级)
Posted 杰西啊杰西
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA06 封装继承多态 总结(初级)相关的知识,希望对你有一定的参考价值。
教程:B站韩顺平
目录
一、访问修饰符
二、封装
- 将属性进行私有化【不能直接修改属性】
- 提供一个公共的set方法,用于对属性判断并赋值
- 提供一个公共的fet方法,用于获取属性的值
tips:将有防护功能的方法写在构造器中,也可以实现防护属性
三、继承
3.1 继承
继承可以解决代码复用,当多个类存在相同属性(变量)和方法时,可以从种抽取父类,在父类中重新定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends继承即可
3.1.1 super关键字
-
super表示父类的引用,用于访问父类的属性,方法,构造器
-
基本语法
- 访问父类的属性,不能访问父类的private属性
super.属性名
- 访问父类的方法,不能访问父类的private方法
super.方法名(参数列表);
- 访问父类的属性,不能访问父类的private属性
-
访问父类的构造器:super(参数列表只能放在构造器的第一句,只能出现一句!)
student.javapublic class student private String name; private int age; public student() public student(String name, int age) setName(name); setAge(age); public void setName(String name) this.name = name; public void setAge(int age) this.age = age; public String getName() return name; public int getAge() return age;
pupil.java
public class pupil extends student private double grades; public pupil() public pupil(String name, int age,double grades) super(name,age); setGrades(grades); public void setGrades(double grades) this.grades = grades; public double getGrades() return grades;
testing.java
public class testing public static void main(String[] args) pupil p = new pupil("小明",18,100.00); System.out.printf("name:%s,\\tage:%d,\\tgrades:%.2f",p.getName(),p.getAge(),p.getGrades());
-
调用方法的顺序:
-
先找本类,如果有,则调用
-
如果没有,则找父类,并可以调用,则调用
-
如果父类没有,则继续找父类的父类,整个规则相同,直到Object类
-
tips:
a. 如果查找方法的过程中,找到了,但是不能访问,则报错
b. 如果查找方法的过程中,没有找到,则提示方法不存在
c. super.cal()是直接查找父类,其他规则一样(从b步骤开始)
d. 当子类中有和父类中的成员(属性和方法)重名是,为了访问父类的成员,必须通过super,如果没有重名,使用super、this、直接访问时一样的效果
e. super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super取访问爷爷类的成员,如果多个基类含有相同的属性名,则使用super访问遵循就近原则,A——>B——>C,同时也需要遵守访问权限的相关规则 -
super和this的比较
-
3.2 继承
3.2.1 概念
- 子类继承了所有类的属性和方法,非私有属性和方法可以在子类中直接访问,但是私有属性不能再子类直接访问,要通过公共的方法访问
- 子类必须调用父类的构造器,完成父类的初始化
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会调用父类的无参构造器
- 如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不通过
- 如果希望指定去调用父类的某个构造器,则显式的调用一下
- super在使用时,需要放在构造器第一行
- super和this都只能放在构造器第一行,因为这两个方法不能共存在同一个构造器中
- java所有类都是Object类的子类,Object是所有类的基类
- 父类构造器的调用不限于直接父类,将一直往上追溯直到Object类(顶级父类)
- 子类最多只能继承一个父类(指直接继承),即java中是单继承方式
- 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系
3.2.2 继承的本质
当子类对象创建好后,建立查找的关系
public class ExtendsTheory
public static void main(Strings[] agrs])
Son son = new Son();
class GrandPa
String name = "爷爷";
String hobby = "旅游";
class Father extends GrandPa
String name = "爸爸";
int age = 39;
class Son extends Father
String name = "儿子";
- 由于只创建一个Son对象,故堆中只划分了一块区域
- 然后再在方法区创建按照 Object——>Son的顺序创建对象
- 调用方法时按照 本类——>Object的顺序进行查找(继承的顺序)
3.2.3 方法重写/覆盖
- 子类方法的形参列表,方法名要和父类的一样
- 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
eg:父类:返回类型Object
子类:返回类型String - 子类方法不能缩小父类方法的访问权限:public>protected>默认>private
3.2.3.1 方法重载和方法重写的比较
四、多态
4.1 方法的多态
重写+重载
4.2 对象的多态
-
一个对象的编译类型和运行类型可以不一致
-
编译类型在定义对象时就确定了,不能改变
-
运行类型是可以变化的
-
编译时类型由声明该变量时使用的类型决定,编译时引用变量只能调用其编译类型所具有的方法。
-
运行时类型由实际赋给该变量的对象决定。
-
编译类型看定义时=的左边,运行类型看=的右边
//Animal.java public class Animal private String name; public Animal() public void cry() System.out.println("cyr:animal"); //Dog.java public class Dog extends Animal public void cry() System.out.println("cry dog"); //Cat.java public class Cat extends Animal public void cry() System.out.println("cry: cat"); //PolyObject.java public class PolyObject public static void main(String[] args) Animal animal = new Dog(); //编译类型:Animal,运行类型Dog animal.cry(); animal = new Cat();//编译类型:Animal,运行类型cat animal.cry();
运行结果:
-
案例
//Animal.java public class Animal private String name; public Animal(String name) this.name=name; public String getName() return this.name; //Dog.java public class Dog extends Animal public Dog(String name) super(name); public void cry() System.out.println("cry dog:"+this.getName()); //Food.java public class Food private String name; public Food(String name)this.name=name; public String getName() return this.name; //Rice.java public class Rice extends Food public Rice(String name) super(name); //PolyObject.java public class PolyObject public static void main(String[] args) Animal animal = new Dog("大黄"); animal.cry(); Food food = new Rice("黑米粥"); Master master = new Master("杰西"); master.feed(animal,food);
4.3 向上转型
-
前提:两个对象(类)存在继承关系
-
本质:父类的引用指向了子类的对象
-
语法:父类类型
引用名=new 子类类型() Animal animal = new Dog();
-
特点:编译类型看左边,运行类型看右边
-
可以调用父类中的所有成员(需要遵循访问权限)
-
不能调用子类中特有成员
-
最终运行效果看子类的具体实现(即运行时,按照运行类型决定)
4.4 向下转型
-
语法:子类类型
引用名 = (子类类型)父类引用; Cat cat = (Cat) animal; //但是要父类的引用必须是指向当前目标类型的引用
-
只能强转父类的引用,不能强转父类的对象
-
要求父类的引用必须指向的是当前目标类型的对象
-
可以调用子类类型中的所有成员
4.5 多态——属性
属性没有重写之说,属性的值看编译类型
4.6 多态——instanceOf
instanceOf比较操作符,用于判断对象的运行类型 是否为xx类型 或者 xx类型的子类型
4.7 动态绑定机制❤️
- 当调用对象方法时,该方法会和该对象的 内存地址/运行类型 绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
4.8 应用
4.8.1 多态数组
例1:
public class PolyArray
public static void main(String[] args)
Person[] persons = new Person[5];
persons[0] = new Student("小明",100);
persons[1] = new Student("大明",400);
persons[2] = new Teacher("大强",20000);
persons[3] = new Teacher("小强",50000);
persons[4] = new Teacher("中强",90000);
for(int i=0;i<persons.length;i++)
persons[i].say();
if(persons[i] instanceof Student)
((Student) persons[i]).study();
else if(persons[i] instanceof Teacher)
((Teacher) persons[i]).teach();
else
System.out.println("类型错误");
class Person
private String name;
public Person(String name)
this.name=name;
public String getName()
return this.name;
public void say()
System.out.println(this.name);
class Student extends Person
private double grades;
public Student(String name,double grades)
super(name);
this.grades = grades;
public double getGrades()
return grades;
public void say()
System.out.println("学生"+this.getName()+"成绩"+this.getGrades());
public void study()
System.out.println("学生"+this.getName()+"正在学习");
class Teacher extends Person
private double salary;
public Teacher(String name,double salary)
super(name);
this.salary = salary;
public double getSalary()
return salary;
public void say()
System.out.println("教师"+this.getName()+"薪酬"+this.getSalary());
public void teach()
System.out.println("教师"+this.getName()+"正在教书");
4.8.2 例题
//Employee.java
public class Employee
private String name;
private double salary;
public Employee(String name, double salary)
this.name=name;
this.salary=salary;
public String getName()
return name;
public double getSalary()
return salary;
public double getAnnual()
return this.salary*12;
//CommenEmployee.java
public class CommenEmployee extends Employee
public CommenEmployee(String name, double salary)
super(name,salary);
public void work()
System.out.println("普通员工:"+super.getName()+"正在工作");
//Manager.java
public class Manager extends Employee
private double bonus;
public Manager(String name,double salary,double bonus)
super(name,salary);
this.bonus = bonus;
public double getBonus()
return bonus;
public void manage()
System.out.println("经理:"+super.getName()+"正在管理");
//PolyParametersTesting.java
public class PolyParameterTesting
public void showEmpAnnual(Employee e)
double salary = e.getSalary();
if(e instanceof Manager)
salary+=((Manager) e).getBonus();
System.out.println(salary);
public void testWork(Employee e)
if(e instanceof CommenEmployee)
((CommenEmployee)e).work();
else if(e instanceof Manager)
((Manager)e).manage();
else
System.out.println("类型出错");
//PolyParameters.java
public class PolyParameter
public static void main(String[] args)
Employee[] es = new Employee[2];
es[0] = new CommenEmployee("员工",1000);
es[1JAVA06 封装继承多态 总结(初级)