继承和多态

··

一. 继承

        1.1 何为继承?

简单来说:就是对共性的抽取,从而达到代码的复用

        

class Animal{
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String name;
    public int age;

    public void eat(){
        System.out.println(name+"正在吃饭!");
    }
}

class Dog extends Animal{    //Dog 就是子类 继承了 父类的 Animal
    public Dog(String name,int age) {
        super(name, age);
    }
    public void bark(){
        System.out.println(name+"汪汪叫!");
    }
}

class Cat extends Animal{
    public Cat(String name,int age) {
        super(name,age);
    }

    public void catchMouse(){
        System.out.println(name+"正在抓老鼠!");
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog("旺财",5);
        Cat cat = new Cat("咪咪",6);
        dog.bark();
        cat.catchMouse();
    }
}

Dog 与 Cat 类 都有共同的属性:name,age 所以我们建立一个父类 Animal 将共有的属性抽出来,减少了代码长度

简而言之就是将:相同属性抽出来

子类叫 派生类

父类叫 基类 也叫超类

当子类 继承 父类 会把属性 和 方法 全部继承!

        1.2 父类成员访问

①. 当父类与子类都拥有 同名的变量时,优先访问子类自己!

②.方法也是如此,若名称完全相同,有时候需要看参数配对!

但如果子类和父类同名时非要访问 父类时我们要怎么做呢?

        加super!

class A{
    public int a=0;
    public int b=0;
    public int c=0;
}

class B extends A{
    int a;
    int b;
    int c;
    public void method(){
        super.a = 10;       //当父类和子类拥有相同的 (同名的)变量时,优先访问子类自己
        b = 20;
        c = 30;
        System.out.println(super.a);    10
        System.out.println(a);    0    
        System.out.println(super.b);    0
    }
}

1. 每一个类 都会生成自己的字节码文件! 不能多继承(接口解决)

        ①.this 会优先访问 子类自己,如果 子类没有,访问的是父类的

        ②.super 只是一个关键字,在代码层面,仅仅只是达到易读效果!!!

super不是父类的引用!

        1.3 super

super的作用就是 在子类方法中访问父类的成员 

        super的三种用法

1. super.data;        调用父类的普通成员变量

2.super.func();       调用父类的普通成员方法

3.super();        调用父类的构造访问 

要注意的是:
super只能在非静态的情况下使用

因为在静态的情况下不依赖对象所以不能使用 this super 

        1.4 子类的构造

先给父类构造 super必须第一行

class Animal{
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String name;
    public int age;

    public void eat(){
        System.out.println(name+"正在吃饭!");
    }
}

class Dog extends Animal{    //Dog 就是子类 继承了 父类的 Animal
    pubilc boolean silly;
    public Dog(String name,int age) {
        super(name, age);
        //1.先帮父类初始化
        this.silly = ture;
    }
    public void bark(){
        System.out.println(name+"汪汪叫!");
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog("旺财",5);
       
        dog.bark();
        
    }
}

注意:
       1.若没有父类显式定义无参或默认的构造方法,在子类构造方法第一行默认有隐含的super()调用。即调用基类构造方法

        2.如果父类构造方法是带有参数的,需要子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用!

        3.在子类构造方法中,super调用父类构造方法中必须 是子类构造方法中的第一条语句!

        4.super不能和this同yo时出现,super只能出现一次

        1.5        super和this

不同点:
1.this 是对当前对象的引用,当前对象即调用实例方法的对象,super相当于子类对象中从父类继承下来的成员的引用!

//引用对象不同

2.this 是访问本类的方法与属性,super是访问父类继承下来的方法与属性

3.在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法

二者不能同时存在!

//访问对象不同

4. 构造方法一定存在super(..)的调用,this(..)用户不写,就没有!

class Animal{
    static {
        System.out.println("Animal::static");    //①
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Animal(String name, int age)");    //②
    }
    {
        System.out.println("Animal::{}");    //③
    }
    public String name;
    public int age;

    public void eat(){
        System.out.println(name+"正在吃饭!");
    }
}

class Dog extends Animal{
    static {
        System.out.println("Dog::static");    //④
    }
    public String name;
    public int age;
    public Dog(String name,int age) {
        super(name, age);
        System.out.println("Dog(String name,int age)");    //⑤
    }
    {
        System.out.println("Dog::{}");    //⑥
    }
    
    public void bark(){
        System.out.println(name+"汪汪叫!");
    }
}

六个sout顺序是如何呢?

1-4-3-6-2-5

顺序是:静态先执行 在分别执行实例代码块+构造!


        1.6 protected

不同包的子类--同一包的不同类:在另一个包也可以访问!

        1.7final修饰

①.修饰变量和字段,表示常量(不能修改)

final int a = 10;

a = 20;//error

②.修饰类:表示此类不能被继承

final public class Animal{
    ...
}

public class Bird extends Animal{
    ...
}    //error

③.修饰方法


二.多态:同一事件发生在不同对象身上,结果确实不一样,这种思想叫多态

        对象不一样,行为就可能不一样!!

        2.2 多态实现条件:

1.必须在继承体系中

2.子类对父类重写

                简简单单举个例子:

//Animal
pubilc void eat(){
    System.out.println(name+"吃饭!");
}

//Dog
public void eat(){
    System.out.println(name+"正在吃狗粮!");
}

Dog类中就实现了对eat的重写:

1.方法名称相同,返回值相同

2.参数列表相同

注意的是 这俩个类 可以不用public修饰,但要遵守的规则是:
子类的访问权限 >=  父类的访问权限

所以子类要么写public 要么不写

以下不可以重写:
1.private修饰的方法不可用于重写

2.final为 密封方法 不可重写

3.被static修饰的方法 不可以重写!   


        2.3        重写

定义:也叫覆盖。重写的是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重写编写,返回值和形参都不能改变。即外壳不变,核心重写!其好处在于 子类可以根据需要,定义特定于自己的行为。也就是子类能根据需要实现父类的方法!

规则:

1.子类在重写的过程中,一般必须与父类方法原型相同:返回值 方法名 参数列表 要相同!

2.返回值也可以不同,但必须构成父子关系!

3.父类被static,private修饰的方法,构造方法都不能被重写!

4.需要override注解


这里可以延申一个面试的小问题:
重写与重载的区别

也就是在参数列表,返回值不一样

重载的参数列表不同,返回值不做要求

重写的参数列表相同,返回值相同,构成父子关系也可以


静态绑定

 

 编译的时候 根据你传入的数据 来确定你调用哪个方法,这种就叫静态绑定!

        

        2.4        向上转型/向下转型

2.4.1        向下转型        子类对象对父类 

public static void main(String[] args){
    Dog dog = new Dog();
    //animal这个引用指向了dog对象
    Animal animal = dog;
    //animal 没有的属性不能访问!

    animal.eat():
}

eat方法 animal和dog类都有 所以可以访问

因此:向上转型只调用自己特有的属性和重写

         这里eat方法的调用要注意的是:编译的时候 调用的还是Animal的eat,但程序运行的时候,变成了子类的eat,这就是动态绑定!

         介绍一下写法:
1.直接赋值

Animal animal2 = new Dog();
Animal animal3 = new Cat();

2.利用参数接收

3.利用方法的返回

 

在main直接调用就行!

        2.4.2        向下转型

 

尽量不要使用,非常危险 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值