教程:B站韩顺平

tips:将有防护功能的方法写在构造器中,也可以实现防护属性
继承可以解决代码复用,当多个类存在相同属性(变量)和方法时,可以从种抽取父类,在父类中重新定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends继承即可
super表示父类的引用,用于访问父类的属性,方法,构造器
基本语法
super.属性名
super.方法名(参数列表);
访问父类的构造器:super(参数列表只能放在构造器的第一句,只能出现一句!)
student.java
public 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的比较

当子类对象创建好后,建立查找的关系
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 = "儿子";
}


重写+重载
一个对象的编译类型和运行类型可以不一致
编译类型在定义对象时就确定了,不能改变
运行类型是可以变化的
编译时类型由声明该变量时使用的类型决定,编译时引用变量只能调用其编译类型所具有的方法。
运行时类型由实际赋给该变量的对象决定。
编译类型看定义时=的左边,运行类型看=的右边
//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);
}
}
前提:两个对象(类)存在继承关系
本质:父类的引用指向了子类的对象
语法:父类类型
引用名=new 子类类型()
Animal animal = new Dog();
特点:编译类型看左边,运行类型看右边
可以调用父类中的所有成员(需要遵循访问权限)
不能调用子类中特有成员
最终运行效果看子类的具体实现(即运行时,按照运行类型决定)

语法:子类类型
引用名 = (子类类型)父类引用;
Cat cat = (Cat) animal; //但是要父类的引用必须是指向当前目标类型的引用
只能强转父类的引用,不能强转父类的对象
要求父类的引用必须指向的是当前目标类型的对象

可以调用子类类型中的所有成员
属性没有重写之说,属性的值看编译类型
instanceOf比较操作符,用于判断对象的运行类型 是否为xx类型 或者 xx类型的子类型


例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()+"正在教书");
}
}
//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[1] = new Manager("经理",2000,500);
PolyParameterTesting ppt = new PolyParameterTesting();
for(int i=0;i<es.length;i++){
ppt.showEmpAnnual(es[i]);
ppt.testWork(es[i]);
}
}
}
是Object类中的方法,只能判断引用类型
默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等
public boolean equals(Object obj){
return (this ==obj);
}
public boolean equals(Object obj){
if(obj instanceOf Integer){
return value=((Integer)obj).intValue();
}
return false;
}
默认返回:全类名+@+哈希值的十六进制【查看Object的toString方法】
子类往往重写toString 方法,用于返回对象的属性信息
public String toString(){
return getClass().getName()+'@'+Integer.toHexString(hashCode());
}
重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString形式
public class Employee {
private String name;
private double salary;
public Employee(String name, double salary){
this.name=name;
this.salary=salary;
}
public String toString(){
return "Employee{" +
"name='"+name+'\'' +
"salary="+salary+'\''+
'}';
}
}
当直接输出一个对象时,toString方法会被默认的调用