package com.day11.inheritence;
/*
从现有类创建(衍生)子类,现有类称为父类,基类,超类
子类会继承父类的所有成员 构造器除外
子类继承父类的语法:class 子类extends 父类{}
子类继承父类私有成员时,父类必须提供公共的方法以间接的使用这些成员
方法覆盖(override):在子类中重写父类的方法,因为父类的方法不能满足需要;
覆盖条件
1)父类中和子类中的方法的签名要完全一致,方法签名包括 返回值类型方法名(参数列表)一致,参数列表一致体现类型,个数,顺序都一致
2)子类方法中的方法控制修饰符要大于等于父类的,如果父类方法时public,子类只能必须时public
super表示超级的意思,作用是特别指定后面的成员是从父类继承的
this表示当前对象,是一个整体
super只是一个标识,用于表示从父类继承的成员
创建子类时会调用到父类的构造器
如果在子类构造器中什么也没有时,编译器会自动添加一个语句super();作用是直接调用父类的无参构造器
如果已经右super(),编译器不做处理
直接效果就是,子类的构造器一定会默认的调用父类的无参构造器
super()语句必须是构造器中的第一行,目的保证了父类构造器必须先指向
父类的无参构造器默认会被所有子类调用,所以在父类中提供无参构造器是非常重要其必须的
关于构造器
1.子类构造中必须有--先对--父类构造器的调用!!!子类构造器第一行,只能是 super(...)或this(...)
1)子类构造器中的第一行 可以是super(...),作用直接显式的调用父类构造器,如果子类构造器中是空的,默认添加super(...)
2)子类构造器中的第一行 可以是this(...),作用是调用本类重载构造器,目的确实间接调用父类构造器
2.所有类都必须要与构造器
多态:子类对象的多种父类形态
本态:子类对象的本类形态
多态引用:子类对象赋值于父类类型的引用变量
本态引用:子类对象赋值于本类类型的引用变量
看右面 子类对象的多种父类形态
看左面 父类类型的引用的多态性
若编译时类型和运行时类型不一致,就出现多态(Polymorphism)
编译时类型(左边)和运行时类型(右边)不一致时,就出现了多态
*/
public class Person {
private String name;
private int age;
private String gender;
public Person() {
System.out.println("Person()");
}
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
System.out.println("Person(String,int,gender)3");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Person" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\''
;
}
public void sayHello(){//虚拟方法:唯一的作用就是骗过编译器
System.out.println("hello");//不执行
}
}
package com.day11.inheritence;
public class Chinese extends Person{
String zodiac;
//子类构造器第一行,只能是 super(...)或this(...)
public Chinese() {
// 如果在子类构造器中什么也没有时,编译器会自动添加一个语句super();作用是直接调用父类的无参构造器
//super("张三",20,"男");//显式的直接调用了父类的有参构造器,如果有显式的调用,隐式调用不调。
//zodiac = "未知";
this("张三",20,"男","未知");
System.out.println("Chinese()1");
}
//全参构造器
public String getZodiac() {
return zodiac;
}
public void setZodiac(String zodiac) {
this.zodiac = zodiac;
}
public Chinese(String name, int age, String gender, String zodiac) {
//子类中不可直接发访问父类继承来的私有成员
super(name, age, gender);//直接显式的调用父类的全参构造器,借用父类构造器完成子类从父类继承的私有成员的初始化
this.zodiac = zodiac;
System.out.println("String name, int age, String gender, String zodiac2");
}
public void spring(){
System.out.println(getName()+"想过年");//子类不可以直接访问父类继承的私有成员
//子类必须通过从父类继承的公共的get/set方法间接方法从父类继承的私有成员
}
@Override//方法的覆盖(重写)子类的方法会覆盖父类的方法
public String toString() {
return super.toString()+",zodiac:"+zodiac;
}
@Override
public void sayHello(){
System.out.println("吃了吗");
}
}
package com.day11.inheritence;
public class American extends Person {
private boolean hasGun;
public American() {
System.out.println("American()");
}
public American(String name, int age, String gender, boolean hasGun) {
super(name, age, gender);
this.hasGun = hasGun;
}
public void christmas() {
System.out.println("merry christmas");
}
public boolean isHasGun() {
return hasGun;
}
public void setHasGun(boolean hasGun) {
this.hasGun = hasGun;
}
@Override
public String toString() {
return super.toString()+"American{" +
"hasGun=" + hasGun +
'}';
}
@Override
public void sayHello(){
System.out.println("how ary you");
}
}
package com.day11.inheritence;
import javax.swing.*;
public class PersonTest {
public static void main(String[] args) {
Chinese ch = new Chinese();
// ch.setName("张三");
// ch.setAge(29);
// ch.setGender("男");
ch.zodiac="虎";
System.out.println(ch.getName());
System.out.println(ch.getAge());
System.out.println(ch.getGender());
System.out.println(ch.zodiac);
ch.spring();
System.out.println(ch.toString());//执行时,执行的是子类的方法,因为父类的方法被覆盖了
// System.out.println(ch.super.toString());在测试类中尝试再去使用被覆盖的方法,不允许
}
}
package com.day11.inheritence;
public class PersonTest4 {
public static void main(String[] args) {
Person p = new Chinese();//只是把chinese看做是Person
//p.spring();多态引用中子类特有的成员不可以访问。。多态副作用!
//多态引用调用覆盖方法
//虚拟方法调用(Virtual Method Invocation)
//动态绑定:在运行时,究竟执行谁的方法时不确定,要取决于new的对象实体
p.sayHello();//编译时检查父类类型,运行时执行子类类型
p = new American(); //p引用指向的对象实体出现了不确定性
p.sayHello();
}
}
1. 子类继承了什么? 能继承父类的私有成员吗? 如何处理?
子类继承了父类的所有成员(变量,方法)
子类继承了父类的私有成员
1)构造器的初始化;
2)get/set(父类里的)
2. 为什么父类又叫基类或超类?
extends:子类 extends 父类
super:super;
3. 什么是方法覆盖? 方法覆盖有什么条件?
Override:如果子类中有一些需求是父类的方法直接拿过来没法用,满足不了
那么,子类就可以重写(Override)父类的方法
private(不行):修饰符(子类要大于等于父类的权限)
返回值 方法名 (参数)完全一致
4. 如果A类被B类继承,B类又被C类继承, 在所有类中都有一个方法test(),
创建C类对象,调用test()方法,执行的是哪个类的方法? 在C类中有几个test()方法?
C类对象的test()
3个,A\B\C的test方法都有
从测试类角度来看C类, 只有一个test方法
从C类内部来看,有两个test方法, 一个是this.test(), 一个是super.test()
从继承的概念来看, 有3个
- 子类构造器中第一行有什么特别要求? 为什么?
要么super(可以有参数)要么this(可以有参数)
super(…) 作用是直接调用父类构造
this(…) 作用是间接调用父类构造.
如果是一个子类对象,调用super()来先初始化从父类继承的那部分成员;
this:本类下的其他构造方法;
结论 : 子类构造器中必须要有先对父类构造器的调用…
创建子类对象
- 检查继承体系中的所有类模板
- 如果没有, 加载时按先父后子的顺序加载类
- 如果有不加载
- 依据继承体系中的所有的类模板中属性的定义信息
- 全部写0
- 执行父类的显式赋值
- 执行父类构造器
- 执行子类显式赋值
- 执行子类构造器
访问权限修饰符
private 本类
default 本类 本包
protected 本类 本包 不同包子类
public 全局
多态:看右面,子类的对象的多种父类形态,看左面,父类类型的引用指向的多种不确定子类对象 把子类对象”看作是“父类对象来使用 本态:对象的本态形态 多态引用:子类对象赋值于父类类型的引用变量,父类类的引用指向子类对象 本态引用:子类对象赋值于父类类型的引用变量