欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JAVASE面向对象-继承(继承特点,this与super关键字,方法重写以及final关键字)

程序员文章站 2022-03-26 16:51:53
1.继承的引入在生活中,有形形色色的继承,最常见的继承是一个家族财产的继承关系,儿子可以继承父亲的财产。在Java中也存在继承关系,Java中的继承是子类可以继承父类的成员(成员变量与成员方法)。Java中继承关系的语法为:用extends关键字来进行继承,让类与类之间产生继承关系。下面我们先用生活中一个简单的例子来引入Java中的继承关系:我们知道动物里面有很多类别,例如猫,狗之类的,都有一些共性的东西。例如吃饭,睡觉等。那么我们就可以将这些共性的东西向上抽取到Animal这个类中,在子类中直接...

1.继承的引入

在生活中,有形形色色的继承,最常见的继承是一个家族财产的继承关系,儿子可以继承父亲的财产。在Java中也存在继承关系,Java中的继承是子类可以继承父类的成员(成员变量与成员方法)。
Java中继承关系的语法为:
用extends关键字来进行继承,让类与类之间产生继承关系。

下面我们先用生活中一个简单的例子来引入Java中的继承关系:
我们知道动物里面有很多类别,例如猫,狗之类的,都有一些共性的东西。例如吃饭,睡觉等。那么我们就可以将这些共性的东西向上抽取到Animal这个类中,在子类中直接就会继承,可以大量的减少代码量,实现代码的实用性与维护性。

//父类:
public class Anmial {
    //将子类共有的东西向上抽取到父类,以实现代码的复用性与维护性
    public String name;
    public int age;
    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
}
//子类:
public class Cat extends  Anmial {
    //子类中可以保留自己特有的方法
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}
public class Dog extends Anmial {
    public void lookDoor(){
        System.out.println("小狗看门");
    }
}
//测试类:
public class MyTest {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.name="胖橘";
        cat.age=3;
        System.out.println(cat.name);
        System.out.println(cat.age);
        cat.eat();
        cat.sleep();
        cat.catchMouse();
        System.out.println("================");
        Dog dog = new Dog();
        dog.name="小强";
        dog.age=5;
        System.out.println(dog.name);
        System.out.println(dog.age);
        dog.eat();
        dog.sleep();
        dog.lookDoor();
    }
}


运行的结果为:
胖橘
3
吃饭
睡觉
猫抓老鼠
================
小强
5
吃饭
睡觉
小狗看门

  • 继承的利弊分析
继承的好处 继承的弊端
提高了代码的复用性与维护性 让类与类之间产生了依赖的关系,增加了耦合性
继承是多态的前提,有了继承才能谈及多态 当依赖关系太过于紧密时,会违背软件的设计原则:高内聚,低耦合
让类与类之间有了继承关系 耦合性过高时,不利于软件后期的维护和扩展

2.继承的特点

  • Java中继承语法:Java中只支持单继承,不支持多继承。可以支持多层继承
  • Java中子类只能继承父类的非私有成员。私有成员,子类不能继承。
  • 构造方法不参与继承
  • 静态方法可以继承
//Object 是我们Java继承体系当中的顶层父类
//所有的类都是直接或间接继承自他。
public class MyTest2 extends Object{
    public static void main(String[] args) {
        /*Java中继承的语法特点
        1.Java中只支持单继承
        一个子类只能有一个父类,
        一个父类是可以有多个子类。
        不支持多继承。可以支持多层继承。
        2.子类只能继承父类非私有的成员。私有的成员,子类不能继承。
        3.构造方法,不参与继承。构造方法,在你初始化子类对象时,
            会调用父类构造来完成父类数据的初始化。
        4.静态方法也是可以继承的。*/

        D d = new D();
        d.hehe();

        D.hehe();


    }
}

class A extends Object{
//子类不能继承父类中的私有变量
   private int a=10;
    public void a(){

    }
}

class B extends A{
    int b=100;
    //子类不能继承父类的私有方法
    private void b(){}
}

class C extends B{
    int c=70;
    public void c(){}
    public static void hehe(){

    }
}
class D extends C{

}
}

  • 当我们创建子类对象时,会先调用父类的构造方法的原因:当我们去创建子类对象时,子类会继承父类的一些数据,会先完成父类数据的初始化,然后初始化自己的数据
public class MyTest {
    public static void main(String[] args) {
        /*当我们创建子类对象时,会先调用父类的构造方法,为什么?
        当我们去创建子类对象时,子类要继承父类的一些数据甚至还要去使用,
        那如果子类的数据没有完成初始化,子类能继承吗?肯定不行。
        所以当我们创建子类对象时,应该先完成父类数据的初始化,
        然后在初始自己的数据。
         */
        /*创建子类成员变量时,会先调用父类的构造方法,
        然后在调用子类构造方法
         */
        Zi zi = new Zi();

    }
}

class Fu extends Object{
    int a=20;
   public Fu(){
       super();
       System.out.println("父类的构造方法执行了");
   }
}

class Zi extends Fu{
    public Zi(){
        super(); //调用父类的空参构造
        System.out.println("子类的构造方法执行了");
    }
}

3.this 、super关键字

super关键字
super:表示父类的空间标识,可以简单理解为父类的一个引用,使用super可以调用父类的数据
super.变量名:调用父类的变量
super.方法名():调用父类的方法
super():调用父类的空参构造
super(有参):调用父类的有参构造
this关键字
this:表示本类的一个引用,谁调用这个方法,方法中的this就代表谁
this.变量名:调用本类的变量
this.方法名():调用本类的方法
this():调用本类的空参构造
this(有参):调用本类的有参构造
public class MyTest {
    public static void main(String[] args) {
        ZZ zz = new ZZ();
        zz.ziHeHe(140);
    }
}
class FF{
    int num=20;
    private int bb=250;
    public int cc=1405;

    public void fuShow(){
        System.out.println(num+"父类的方法");
    }
    public int  getBB(){
        return this.bb;
    }
}
class ZZ extends FF{
    int z=100;
    int num=800;

    public void ziHeHe(int num) {
        /*
          变量访问的就近原则。
        * 当我们在方法中访问一个变量的时候,先从局部范围找,
          找到就使用,如果没找到,去本类的成员范围找,找到就使用,
        * 如果没找到,会去父类的成员范围找,找到就使用
        * 局部变量和成员变量以及父类的成员变量重名问题,
          可以使用  this super 来区分
        * */

        System.out.println(num);//140
        System.out.println(this.num);//800
        System.out.println(super.num);//20
        System.out.println(cc);
    }
    public void ziShow(){
        System.out.println(this.z);
        System.out.println(this.num);
        System.out.println(super.num);
        this.fuShow();
        super.fuShow();
       // System.out.println(super.bb); 报错
        int bb = this.getBB();
        int bb1 = super.getBB();
        System.out.println(bb);
        System.out.println(bb1);

    }


}

4.方法重写

在继承关系中,当子类与父类存在一模一样的方法,可以进行方法重写。

  • 方法重写:子类中出现与父类一模一样的方法(方法名,参数列表以及返回值的类型),也称为方法重写或者方法覆盖。
  • 子类会覆盖父类的方法,实际运行时,运行的是子类重写过的方法
  • 方法重写的机制:一个父类会有多个子类,父类里面抽取的是所有子类共性的功能,但每个子类对于共性功能的具体实现,存在差异。
  • 子类方法重写的目的:就是对父类功能实现不满意,想要根据自己的需求,进行重写与扩展

4.1 方法重写(功能重写)

//父类
public class Animal {
	//对于子类*性功能进行提取
    public void eat() {
        System.out.println("吃饭");
    }

    public void sleep() {
        System.out.println("睡觉");
    }
}
//子类
public class Cat extends Animal{
    public void catchMouse(){
        System.out.println("抓老鼠");
    }

    public void eat(){
        System.out.println("猫爱吃小鱼干");
    }

    public void sleep(){
        System.out.println("猫喜欢白天睡觉");
    }

}
public class Dog extends Animal{
    public void lookDoor(){
        System.out.println("狗看门");
    }

    public void eat(){
        System.out.println("狗吃骨头");
    }
}
//测试类
public class MyTest {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.eat();
        cat.sleep();
        System.out.println("=====================");
        Dog dog = new Dog();
        dog.sleep();
        dog.eat();
    }
}


输出的结果为:

猫爱吃小鱼干
猫喜欢白天睡觉
=====================
睡觉
狗吃骨头

4.2 方法重写(功能扩展)

  • 对于某部分代码满意,还想扩展,也可以通过方法重写来实现
//父类:手机类
public class Phone {
    public Phone() {
        System.out.println("构造方法执行了");
    }

    public void call() {
        System.out.println("打电话 ");
    }

    public void send() {
        System.out.println("发短信");
    }
}
//子类:Iphone手机
public class Iphone extends Phone{
    public void palyGame(){
        System.out.println("玩游戏");
    }

    @Override //注解   
    // @Override 这个注解的作用,是用来检测此方法是不是重写父类的方法
    public void call() {
        super.call(); //沿袭父类的功能
        System.out.println("高清视频通话");
    }
}
//测试类:
public class MyTest {
    public static void main(String[] args) {
        Iphone iphone = new Iphone();
        iphone.call();
        iphone.send();
        iphone.palyGame();
    }
}

输出的结果为:
打电话
高清视频电话
发短信

4.2 方法重写的注意事项

方法重写的注意事项
父类的私有方法,子类不能进行重写(因为父类的私有方法,子类都不能继承,就更不能进行重写
父类的构造方法不能重写(构造方法不参与继承)
静态方法不参与重写
子类在重写父类方法时,方法的权限修饰符,不能比父类的低,可以与父类的权限修饰符保持一致(权限:public>protected>缺省>私有)
public class MyTest {
    public static void main(String[] args) {
        //方法重写时,需要注意的事项。
        //1.父类私有的方法,子类不能重写,私有方法,子类不能继承
        //2.父类构造方法,不能重写,构造方法没有继承一说。
        //3.子类在重写父类方法时,方法的权限修饰符,
        // 不能比父类的低可以跟父类的一样,或者比父类的高
        //public>protected>缺省的>private
        //4.静态方法,不参与重写

        Father.haha();

        Son son = new Son();
        son.haha();
        Son.haha();

    }

}

class Father{
    private void show(){

    }

    protected void hehe(){

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

}
class Son extends Father{
    @Override
    protected void hehe() {

    }

    //@Override  静态方法不参与重写
    public static void haha() {
        System.out.println("子类的静态方法");
    }

}

5.final关键字

  • final关键字是最终的意思,可以修饰类,变量,成员方法。
final修饰特点
修饰类: 被修饰类不能被继承
修饰方法: 被修饰的方法不能被重写
修饰变量: 被修饰的变量不能被重新赋值,因为这个量其实是一个常量
public class MyTest {
    //公共的静态常量
 public static final double AA=3.14; //自定义常量
    public static void main(String[] args) {
        //final 最终的,可以修饰成员变量,局部变量,形参,也可以修饰方法,也可以修类
        //修饰变量,此变量为一个常量,既然为常量,常量的值就不能再次被改变。
        //自定义常量,常量名一般建议大写
        final int NUM=100;
              //NUM=200; //重新赋值,报错,常量不能再次赋值
        System.out.println(NUM);
        double aa = MyTest.AA;
        System.out.println(aa);

        BB bb = new BB();
        System.out.println(bb);
           bb=new BB();
        System.out.println(bb);

        System.out.println("============================");
       final BB bb1 = new BB();
        //final修饰的是基本类型,指的是值不能再次被改变。
        //final修饰的是引用数据类型,指的是这个地址值,不能再次被改变
        //final修饰方法,此方法,不能被子类重写,但是可以让子类继承去用
        CC cc = new CC();
        cc.show();
        //final 修饰类,此类不能被继承
      
    }
}

class BB{
   public final void show(){
       System.out.println("父类的final修饰的方法,子类不能重写,子类可以继承");
   }
}

class CC extends BB{
 /*   @Override
    public void show() {

    }*/
}
//final修饰类,此类不能被继承
 final class EE{

}
/*
class FF extends EE{

}
*/

本文地址:https://blog.csdn.net/qq_41537102/article/details/110225610

相关标签: JAVASE java