Java第二阶段---12继承---第二节 方法重写(override)

1.概念

子类中的一个成员方法与父类中的成员方法有相同的签名(方法名加上参数数量和参数类型)和返回值类型的实例方法重写了父类的方法

2.如何使用方法重写

子类重写方法的能力使类可以从行为“足够近”的父类继承,然后根据需要修改行为。重写方法与被重写的方法具有相同的名称,数量和参数类型,并且返回类型相同。重写方法还可以返回重写方法返回的类型的子类型,此子类型称为协变返回类型。

重写方法时,您可能需要使用@Override注解,该注释指示编译器您打算重写父类中的方法。如果由于某种原因,编译器检测到该方法在父类中不存在,则它将生产错误。

byte short int long float double

数字对应的类:Byte Short Integer Long Float Double => 都是Number的子类

3.案例

几何图形都有面积和周长,不同的几何图形,面积和周长的算法也不一样。矩形有长和宽,通过长和宽能够计算矩形的面积和周长;圆有半径,通过半径可以计算圆的面积和周长。请使用继承相关的知识完成程序设计。

package com.cyx.inheritance.shape;

/**
 * 几何图形
 */
public class Shape {
    /**
     * 计算周长
     * @return
     */
    public Number calculatePerimeter(){
        return 0;
    }

    /**
     * 计算面积
     * @return
     */
    public Number calculateArea(){
        return 0;
    }
}

package com.cyx.inheritance.shape;

/**
 * 矩形
 */
public class Rectangle extends Shape {

   private int width;
    private int length;

    //生成构造方法
    public Rectangle(int width, int length) {
        this.width = width;
        this.length = length;
    }

    public Integer calculatePerimeter(){
        return (width+length) * 2;
    }

    public Integer calculateArea(){
        return width * length;
    }
}


package com.cyx.inheritance.shape;

/**
 * 圆
 */
public class Circle extends Shape {
   private int radius;

    public Circle(int radius) {
        this.radius = radius;
    }

    @Override
    public Double calculatePerimeter(){
        return 2 * Math.PI * radius;
    }

    @Override
    public Double calculateArea(){
        return Math.PI * radius * radius;
    }
}


package com.cyx.inheritance.shape;

public class ShapeTest {

    public static void main(String[] args) {
        Shape s1 = new Rectangle(10,9);
        System.out.println(s1.calculatePerimeter());
        System.out.println(s1.calculateArea());


        Shape s2 = new Circle(5);
        System.out.println(s2.calculatePerimeter());
        System.out.println(s2.calculateArea());
    }
}

重写方法时访问修饰符的级别不能降低

4.super关键字

如果子类的构造方法没有明确调用父类的构造方法,java编译器会自动插入一个父类无参构造的调用,如果父类没有无参构造,你将得到一个编译时错误。Object类有一个无参构造,因此,如果Object类是该类的唯一父类,这就没有问题。

(如果一个类没有构造方法,编译器在编译的时候会自动插入一个无参构造方法)

示例一:子类和父类中都没有定义构造方法

package com.cyx.inheritance;

public class Father {

    public Father(){
        super();
    }
    String name;

    public String sex;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    protected void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}

package com.cyx.inheritance;

public class Child extends Father{
    //如果一个类中没有定义构造方法,那么编译器将会为该类插入一个无参构造方法
    public Child(){
        super();//如果子类构造方法中没有显示的调用父类的构造方法,俺么编译器会自动插入一个父类无参构造的调用
    }
    public void show(){
        System.out.println(name);//本类中未定义name变量,但是却可以使用,说明name变量是从父类中继承过来的
        System.out.println(sex);
        eat();
        sleep();
    }

}

示例二:子类中有定义构造方法,父类中没有定义构造方法

package com.cyx.inheritance;

public class Father {

    String name;

    public String sex;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    protected void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}

package com.cyx.inheritance;

public class Child extends Father{
    //如果一个类中没有定义构造方法,那么编译器将会为该类插入一个无参构造方法
    public Child(){
        super();//如果子类构造方法中没有显示的调用父类的构造方法,俺么编译器会自动插入一个父类无参构造的调用
    }

    public Child(String name){
        super();
        this.name = name;
    }

    public void show(){
        System.out.println(name);//本类中未定义name变量,但是却可以使用,说明name变量是从父类中继承过来的
        System.out.println(sex);
        eat();
        sleep();
    }

}

示例三:子类和父类中都有定义构造方法

package com.cyx.inheritance;

public class Father {

    public Father(String name,String sex){
        this.name = name;
        this.sex = sex;
    }

    String name;

    public String sex;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    protected void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}

package com.cyx.inheritance;

public class Child extends Father{

    //如果父类中定义了带参构造,并且没有定义无参构造,那么必须在子类的构造方法中显示的调用父类的带参构造(即自己把父类的带参写上去)
    public Child(String name,String sex){
        super(name,sex);
    }


    public void show(){
        System.out.println(name);//本类中未定义name变量,但是却可以使用,说明name变量是从父类中继承过来的
        System.out.println(sex);
        eat();
        sleep();
    }

}

使用super调用父类的构造方法时,必须为这个构造方法的第一条语句

如果你的方法重写了父类的方法之一,则可以通过使用关键字super来调用父类中被重写的方法。你也可以使用super来引用隐藏字段(尽管不建议使用隐藏字段)。

package com.cyx.inheritance.p3;

public class Person {

    protected String name;

    protected String sex;

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

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

package com.cyx.inheritance.p3;

public class Student extends Person{

    private String name;//此时这个name 就会将父类中的name隐藏掉

    public Student(String name) {
        this.name = name;
    }

//    @Override
//    public String getName() {
//        return name;
//    }
    public void show(){
        System.out.println(this.name);//访问本类中定义的name变量
        System.out.println(super.name);//访问父类中定义的name变量
        //如果子类中和父类中没有相同的成员变量,此时使用this和super均可以调用父类的成员变量
        System.out.println(this.sex);
        System.out.println(super.sex);



    }

}

package com.cyx.inheritance.p3;

public class PersonTest {

    public static void main(String[] args) {
        Student s = new Student("张三");
        s.setSex("男");
        s.show();
    }
}

思考:如果子类中的静态方法与父类中的静态方法具有相同的签名,是否属于方法重写?

不属于方法重写,因为静态方法称之为类方法,跟对象无关,调用时只看对象的数据类型。

package com.cyx.inheritance.p4;

public class StaticFather {

    public static void show(){
        System.out.println("这是父类的静态方法");
    }
}

package com.cyx.inheritance.p4;

public class StaticChild extends StaticFather{

    public static void show(){
        System.out.println("这是子类的静态方法");
    }
}

package com.cyx.inheritance.p4;

public class StaticTest {
    public static void main(String[] args) {
        StaticFather f = new StaticChild();//跟对象无关,只看类型
        f.show();
        StaticFather.show();
        StaticChild.show();
    }
}

5.万物皆对象

除了没有父类的object之外,每个类都有一个且只有一个直接父类(单继承)。在没有其他任何显示超类的情况下,每个类都隐式为objetc的子类。

类可以派生自另一个类,另一个类又可以派生自另一个类,依此类推,并最终派生自醉顶层的类object。据说这样的类是继承链中所有类的后代,并延伸到object。

所有类都是object的子类,因此,创建对象时都需要调用object类中的无参构造方法,而object本身就表示对象,因此创建出来的都是对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值