JAVA基础语法 day06 继承与多态

一、继承

1.1继承基础知识

使用关键字extend继承,子类可以继承父类的非私有成员,提高代码的复用性。

语法格式:

public class 子类 extends 父类{}

设置父类:

public class People {
    private String name;
    private int age;
    private char gender;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public char getGender() {
        return gender;
    }
}

设置子类

package jmy.oop_plus;

public class Teacher extends People{
    private String skill;

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

}
public class Test {
    public static void main(String[] args) {
        //1.创建对象,封装老师数据
        Teacher t1 = new Teacher();
        t1.setName("李老师");
        t1.setAge(28);
        t1.setGender('男');
        t1.setSkill("教语文");
    }
}

1.2 权限修饰符

权限修饰符的作用:限制类中的成员(成员变量、成员方法、构造器)能被访问的范围

private:只能在本类中

缺省:只能在本类、同一个包中的类

protected:只能在本类、同一个包中的类、以及子孙类

public:任意位置

一般来说,成员变量的属性一遍private,方法public(get和set)

1.3 继承的特点

单继承:子类只有一个父类。因为多继承会导致方法重名冲突

多层继承:孙子继承自父亲,父亲继承自爷爷

祖宗类:java中所有类的祖宗类是Object类。一个类要么直接继承Object,要么间接继承Object

继承后子类访问成员的特点:就近原则:先在子类局部范围找,再在子类成员范围找,然后再父类成员中找,如果父类范围没找到,就报错

如果子父类中出现了重名变量,会优先访问子类中的变量,但如果此时一定要访问父类的变量怎么办?使用super

public class Test {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        b.show();//就近原则,先在子类的范围里找name

    }
}

class A {
    String name = "这是父类的名字";
} //tips:java文件中,可以允许有多个类,但是public的只能有一个,这个公共的类作为文件名,这是龟腚

class B extends A {
    String name = "这是子类的名字";
    public void show(){
        String name = "这是show的name";
        System.out.println(name);
        System.out.println(this.name);//this.name访问的子类这个对象
        System.out.println(super.name);//super 代表父类
    }
}

1.4方法重写

当子类觉得父类中某个方法不好用,无法满足需求的时候,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的方法,即方法重写

在重写一个方法的时候,在上面使用 :“@override”来作为标志,提醒一下。

重写的几个注意点:

1.子类重写父类的方法时,范围必须大于等于父类方法的权限(public > protected>缺省  )

2.重写方法的返回值类型,必须等于或者小于被重现的方法返回值类型

3.静态方法(因为静态的,属于类自己的东西,所以不能重写),私有方法(因为私有的,子类不能继承)不能重写,否则会报错

一个准则:声明不变(直接抄父类的定义),重新实现(方法的功能重新写)

public class Test {
    public static void main(String[] args) {
        cat c = new cat();
        c.cry();
    }
}

class Animals{
    public void cry(){
        System.out.println("Cry!");
    }
}

class cat extends Animals{
    @Override //方法重写的一个注解(标志)作为提醒:方法名称和形参列表必须和被重写方法一致,否则报错
    public void cry(){
        System.out.println("喵喵");//这就是override了
    }
}

方法重写的常见应用场景

1.子类重写父类的tostring方法,以便返回对象的内容

    @Override //toString方法是祖宗类object提供的一个方法,它返回的是一个hashcode,我们需要返回字符串,以便查看
    public String toString() { //重写toString方法,以便打印对象
        return "这是一只猫";
    }

1.5子类构造器的特点

子类的全部构造器,都会先调用父类的构造器,再执行自己的。

super()调用父类的构造器

因为:

默认情况下,子类的第一行都会有super(),写不写都会有,他会调用父类的无参构造器。

如果父类没有无参构造器,必须手写super()出来,去调用父类的有参构造器

public class Test {
    public static void main(String[] args) {
        Son s = new Son();//子类的构造器,必须先调用父类的构造器(有参或无参),再调用自己的

    }

}
class Father{
    private Father(){
        System.out.println("这是父类的构造器");
    }
    public Father(int a){
        System.out.println("这是父类的有参构造器");
    }
}
class Son extends Father{
    public Son(){
        super(666);//使用super,指定调用父类的有参构造器
        System.out.println("这是子类的构造器");
    }
}

子类调用父类构造器的作用:

调用父类的有参构造器,把子类继承自属于父类这部分的数据完成初始化赋值
public class People {
    private String name;
    private int age;
    private char gender;

    public People() {}
    public People(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
public class Teacher extends People{
    private String skill;
    public Teacher(String name, int age, char gender, String skill) {
        super(name,age,gender);//调用父类的有参构造器,把子类继承自父类的数据完成初始化赋值,name,age,gender实际上还是父类的属性
        //需要通过父类的构造器来初始化赋值
        this.skill = skill;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

1.6 this(...)调用兄弟构造器

public class test2 {
    public static void main(String[] args) {
        //使用this(...)去调用兄弟构造器
        Son s2 = new Son("张三",'男');//需求:当不传入age值时,默认输出18,此时需要用this调用兄弟构造器
        System.out.print(s2);
    }
}
    public Son(String name,char sex){
        this(name,18,sex); //this调用兄弟构造器,并把18传进去,作为默认值
        //以后,创建类的实例时,若不传age值,就默认为18
    }
    public Son(String name , int age , char sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "名字: " + name + "年龄 " + age + "性别 " + sex;
    }

二、多态

2.1 认识多态

多态是在继承、实现下的一种现象,表现为行为多态、对象多态

多态的前提:有继承、实现关系,存在父类引用对象,存在方法重写

public class test {
    public static void main(String[] args) {
        //1.对象多态,行为多态
        animal a1 = new wolf();
        a1.run();
        System.out.println(a1.name);//输出:动物。 因为对于成员变量:编译、运行都是看左边。
        // 即看a1的左边,是animal,输出的是animal的name
        animal a2 = new tortoise();
        a2.run(); // 对于方法:编译看左边,运行看右边
        //tips:变量不强调多态性,都是看左边。方法才要看子类的具体情况

    }
}
public class wolf extends animal {
    String name = "狼";
    @Override
    public void run(){
        System.out.println("wolf runs fast");
    }

2.2 多态的好处

1.在多态的情况下,右边的对象是解耦合的,方便扩展和维护。

People p1 = new teacher();
p1.run();

2.在定义方法时,使用父类类型的形参,可以接受一切子类对象,扩展性更强,更便利

        //2.多态的好处
        wolf w = new wolf();
        tortoise t = new tortoise();
        go(w);
        go(t);

    }
    //需求:开发一个游戏,让所有动物都跑起来
    public static void go(animal all_animals) { // 使用父类类型的变量作为参数,可以接受一切子类变量
        System.out.println("开始===========");
        all_animals.run();
    }

2.3多态的一个问题

多态下,调用不了子类的独有功能

        //多态的一个问题
        animal a3 = new wolf();
        //a3.eatSheep(); 报错,因为编译看左边,animal里并没有eatSheep这个方法
        w.eatSheep(); // 想调用子类的方法,必须使用子类对象调用

2.4多态下的类型转换

自动类型转换:子类变量给到父类对象

父类 变量名 = new 子类();

强制类型转换:

子类 变量名 = (子类) 父类变量

强转的时候,要小心,不能把乌龟转成狼/

强转前,可用 instanceof 关键字判断对象的真实类型,再做转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值