主要内容
- 继承
 - 多态
 - 向上转型
 - 向下转型
 - 方法重写
 - 方法重载
 - super关键字
 - 动态绑定
 - 封装访问控制
 - 构造方法规则
 
一、继承
1. 概念:
一句话说就是:"共性抽取,代码复用"
- 
- 子类会将父类中的成员变量或者成员方法继承到子类中
 
 - 
- 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
 
 
2. 语法:
(1) extends
        
            
            
              java
              
              
            
          
          修饰符 class 子类 extends 父类{
	//...
}
        (2) 父类成员访问:
访问1:子类中访问父类的成员变量
- 
- 子类和父类不存在同名成员变量
 
- 正常访问
 
 - 
- 子类和父类成员变量同名
 
循就近原则,自己有优先自己的,如果没有则向父类中找。
- 
如果访问的同名成员变量子类中有 ,优先访问子类自己的成员变量。
 - 
如果访问的成员变量子类中无 ,则访问父类继承下来的 ,如果父类也没有定义 ,则编译报错。
 - 
如果访问的成员变量与父类中成员变量同名 ,则优先访问自己的
 
 
访问2:子类中访问父类的成员方法
- 
成员方法名字不同
- 成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。
 
 - 
成员方法名字相同
javaclass Parent { void show(int x) { System.out.println("Parent:int"); } } class Child extends Parent { void show(String s) { System.out.println("Child:String"); } // 重载 void demo() { show(10); // 调用父类方法 show("hello"); // 调用子类重载方法 } }- 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
 - 通过子类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同++(重载)++ ,根据调用方法适传递的参数选择合适的方法访问,如果没有则报错
 
 
            
            
              java
              
              
            
          
          class Base {
    int a = 10;
    String b = "父类";
    void methodA() { System.out.println("父类方法A"); }
}
class Derived extends Base {
    int a = 20; // 同名成员变量
    void methodA() { System.out.println("子类重写方法A"); } // 方法重写
    void methodB() { System.out.println("子类特有方法B"); }
    
    void test() {
        System.out.println(a);        // 输出20(就近原则)
        System.out.println(super.a); // 输出10(显式访问父类)
        methodA();                   // 调用子类重写方法
        super.methodA();              // 调用父类被覆盖方法
    }
}
        3. super
- 
在子类方法中访问父类的成员。
- 
只能在==非静态方法==中使用
 - 
在子类方法中,访问父类的成员变量和方法。
 - 
super和this:javaclass Animal { String type = "Animal"; } class Cat extends Animal { String type = "Cat"; void print() { System.out.println(this.type); // Cat(当前对象成员) System.out.println(super.type); // Animal(父类成员) } }- 
this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
 - 
- 在非静态成员方法中,
this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性 
 - 在非静态成员方法中,
 - 
- 在构造方法中:
this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现 
 - 在构造方法中:
 - 
- 子类构造方法中一定会存在
super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有 
 - 子类构造方法中一定会存在
 
 - 
 
 - 
 
4. 子类构造方法:
子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。
- 在构造子类对象时候 ,++先要调用基类的构造方法,将从基类继承下来的成员构造完整++ ,然后再++调用子类自己的构造方法,将子类自己新增加的成员初始化完整++
 
            
            
              java
              
              
            
          
          class Person {
    String name;
    Person(String name) { 
        this.name = name; 
        System.out.println("Person构造");
    }
}
class Student extends Person {
    int id;
    Student(String name, int id) {
        super(name); // 必须第一行!
        this.id = id;
        System.out.println("Student构造");
    }
}
public class Main {
    public static void main(String[] args) {
        Student s = new Student("张三", 1001);
    }
}
        输出:
Person构造
Student构造
        - 
注意:
- 
- 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的
super()调用,即调用基类构造方法 
 - 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的
 - 
- 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
 
 - 
- 在子类构造方法中,
super(...)调用父类构造时,必须是子类构造函数中第一条语句。并且只能出现一次。 
 - 在子类构造方法中,
 - 
super(...)只能在子类构造方法中出现一次,并且不能和this同时出现
 
 - 
 
二、封装
(只针对Java,不同语言有些许差异)
| No | 范围 | private | default | protected | public | 
|---|---|---|---|---|---|
| 1 | 同一包中的同一类 | ✓ | ✓ | ✓ | ✓ | 
| 2 | 同一包中的不同类 | ✓ | ✓ | ✓ | |
| 3 | 不同包中的子类 | ✓ | ✓ | ||
| 4 | 不同包中的非子类 | ✓ | 
三、多态
一句话说就是:完成某个行为,当不同的对象去完成时会产生出不同 的状态。
(1) 重写(override):
- 
也称为覆盖。重写是子类对父类非静态、非
private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写! - 
注意:
- 
子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致
 - 
被重写的方法返回值类型可以不同,但是必须是具有父子关系的
 - 
访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被
public修饰,则子类中重写该方法就不能声明为protected - 
父类被
static、private修饰的方法、构造方法都不能被重写。 - 
重写的方法, 可以使用
@Override注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成aet), 那么此时编译器就会发现父类中没有aet方法, 就会编译报错, 提示无法构成重写. 
 - 
 
(2) 重写和重载:
| 区别点 | 重写(override) | 重载(overload) | 
|---|---|---|
| 参数列表 | 一定不能修改 | 必须修改 | 
| 返回类型 | 不能修改(除非是父子类兼容的返回类型) | 可以修改 | 
| 访问限定符 | 不能做更严格的限制(可以相同或更宽松) | 可以修改 | 
(3) 静态绑定和动态绑定:
- 
静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。
 - 
动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法。
 
(4) 多态实现条件:
- 
- 必须在继承体系下
 
 - 
- 子类必须要对父类中方法进行重写
 
 - 
- 通过父类的引用调用重写的方法
 
java父类类型 变量名 = new 子类对象(); 变量名.方法(); // 实际调用的是子类重写的方法javaclass Animal { void sound() { System.out.println("动物叫"); } } class Cat extends Animal { @Override void sound() { System.out.println("喵喵喵"); } // 重写 } public class Main { public static void main(String[] args) { Animal a = new Cat(); // 向上转型 a.sound(); // 输出"喵喵喵"(动态绑定,执行子类方法) } } 
四、向上转移和向下转型:
1. 向上转型:
从小范围向大范围的转换
- 
实际就是创建一个子类对象,将其当成父类对象来使用。
 - 
父类类型 对象名 = new 子类类型()javaAnimal animal = new Cat("kitty",2) - 
使用:
- 
- 
直接赋值
javaAnimal cat = new Cat("kitty",2); //子类对象直接赋值给父类对象 
 - 
 - 
- 方法传参
 
javapublic static void eatFood(Animal a){ a.eat(); } - 
- 
方法返回
javapublic static Animal getAnimal(String type) { if ("dog".equals(type)) { return new Dog(); // 向上转型:Dog→Animal } else if ("bird".equals(type)) { return new Bird(); // 向上转型:Bird→Animal } return new Animal(); } 
 - 
 
 - 
 
2. 向下转型(有风险):
将父类引用再还原为子类对象,即向下转换
            
            
              java
              
              
            
          
          public class Main {
    public static void main(String[] args) {
        Animal animal = new Cat();  // 向上转型
        // 向下转型(必须先向上转!)
        if (animal instanceof Cat) {  // 安全检查
            Cat cat = (Cat) animal;   // 强制转换
            cat.catchMouse();        // 输出"猫抓老鼠"
        }
        // 错误示例:直接转型非子类对象(运行时抛出ClassCastException)
        // Animal dog = new Animal();
        // Cat wrongCat = (Cat) dog;  // 报错!
    }
}
        注意:
- 必须通过 
instanceof检查安全性,避免ClassCastException。 - 只有原本是子类对象的父类引用才能成功向下转型。