Java 面向对象(四)继承

一、继承的概述

  1、由来

    多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

    其中,多个类可以称为 子类,单独的那一个类称为 父类超类super class)或 基类

   继承描述的是事物之间的所属关系,这种关系是 : is - a 的关系。(子类就是一个父类:子类 is a 父类)

   如上图:兔子属于食草动物,食草动物属于动物。可见,父类是通用,子类更具体。通过继承,可以使多种事物之间形成一种关系体系。

  2、定义

    继承:就是子类继承父类的属性行为。使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。

  3、好处

      a、提高代码的复用性

    b、类与类之间产生了关系,是多态的前提

二、继承的格式

    通过 extends 关键字,可以声明一个子类继承另外一个父类。

   定义格式:

// 定义父类
class 父类名称 {
...
}
// 定义子类 class 子类名称 extends 父类名称 { ... }

三、继承后的特点——成员变量

   当类之间产生了关系后,其中各类中的成员变量会产生影响,分为下面两类来讨论:

  1、成员变量不重名

    如果子类父类中出现不重名的成员变量,这时候的访问是没有影响的。

   Demo:

 1 // 父类
 2 class Fu {
 3     // Fu中的成员变量。
 4     int num = 5;
 5 }
 6 // 子类
 7 class Zi extends Fu {
 8     // Zi中的成员变量
 9     int num2 = 6;
10     // Zi中的成员方法
11     public void show() {
12         // 访问父类中的num,
13         System.out.println("Fu num="+num); // 本类中没有,继承而来,所以直接访问。
14         // 访问子类中的num2
15         System.out.println("Zi num2="+num2);   // 本类中有,访问本类中num2
16     }
17 }
18 // 测试类
19 class Test{
20 public static void main(String[] args) {
21     // 创建子类对象
22     Zi z = new Zi();
23     // 调用子类中的show方法
24      z.show();
25     }
26 }
27 
28 演示结果:
29 Fu num = 5
30 Zi num2 = 6

  2、成员变量重名

    如果子类父类中出现重名的成员变量,这时候的访问是有影响的。

     Demo:

 1 class Fu {
 2     // Fu中的成员变量。
 3     int num = 5;
 4 } 
 5 class Zi extends Fu {
 6     // Zi中的成员变量
 7     int num = 6;
 8     public void show() {
 9         // 访问父类中的num
10         System.out.println("Fu num=" + num);
11         // 访问子类中的num
12         System.out.println("Zi num=" + num);
13     }
14 } 
15 class ExtendsDemo03 {
16     public static void main(String[] args) {
17         // 创建子类对象
18         Zi z = new Zi();
19         // 调用子类中的show方法
20         z.show();
21     }
22 } 
23 演示结果:
24 Fu num = 6
25 Zi num = 6    

 

   通过以上Demo可以看出,子父类中出现了同名的成员变量时,在子类中访问父类是访问不到的。

  super 关键字

  在子类中需要访问父类中非私有成员变量时,需要使用 super 关键字,修饰父类成员变量,类似于之前的 this。

  使用格式:

super.父类成员变量名

   将上面的 Demo 中子类方法进行修改:

 1 class Zi extends Fu {
 2   // Zi中的成员变量
 3   int num = 6;
 4   public void show() {
 5     //访问父类中的num
 6     System.out.println("Fu num=" + super.num);
 7     //访问子类中的num
 8     System.out.println("Zi num=" + this.num);
 9   }
10 } 
11 演示结果:
12 Fu num = 5
13 Zi num = 6

 

  Tips:父类中的成员变量是非私有的,子类中可以直接访问。若父类中的成员变量私有了,子类是不能直接访问的。通常,遵循封装的原则,使用 private 修饰成员变量 ,那么访问父类的成员变量就需要使用公开的 setter 和 getter 方法。

四、继承后的特点——成员方法

  当类之间产生了关系,其中各类中的成员方法又会产生影响,下面分两种情况来讨论:

  1、成员方法不重名

    如果子类父类中出现不重名的成员方法,这时调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。

   Demo:

 1 class Fu{
 2   public void show(){
 3     System.out.println("Fu类中的show方法执行");
 4   }
 5 } 
 6 class Zi extends Fu{
 7   public void show2(){
 8     System.out.println("Zi类中的show2方法执行");
 9   }
10 } 
11 public class ExtendsDemo04{
12   public static void main(String[] args) {
13     Zi z = new Zi();
14     //子类中没有show方法,但是可以找到父类方法去执行
15     z.show();
16     z.show2();
17   }
18 }

  2、成员方法重名 —— 重写(Override)

     如果子类父类中出现 重名 的成员方法,这时的访问是一种特殊情况,叫做方法重写(Override)

    方法重写:子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现

    Demo:

 1 class Fu {
 2   public void show() {
 3     System.out.println("Fu show");
 4   }
 5 } 
 6 class Zi extends Fu {
 7   //子类重写了父类的show方法
 8   public void show() {
 9     System.out.println("Zi show");
10   }
11 }
12 public class ExtendsDemo05{
13   public static void main(String[] args) {
14     Zi z = new Zi();
15     // 子类中有show方法,只执行重写后的show方法
16     z.show(); // Zi show
17   }
18 }

     a、重写的应用

        子类可以根据需要,定义特定与自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。

      Demo:新手机增加来点显示头像的功能。

 

 1 class Phone {
 2     public void sendMessage(){
 3         System.out.println("发短信");
 4     }
 5     public void call(){
 6         System.out.println("打电话");
 7     } 
 8     public void showNum(){
 9         System.out.println("来电显示号码");
10     }
11 }
12 //智能手机类
13 class NewPhone extends Phone {
14     //重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
15     public void showNum(){
16         //调用父类已经存在的功能使用super
17         super.showNum();
18         //增加自己特有显示姓名和图片功能
19         System.out.println("显示来电姓名");
20         System.out.println("显示头像");
21     }
22 }
23 
24 public class ExtendsDemo06 {
25     public static void main(String[] args) {
26         // 创建子类对象
27         NewPhone np = new NewPhone();
28         // 调用父类继承而来的方法
29         np.call();
30         // 调用子类重写的方法
31         np.showNum();
32     }
33 }        
View Code  

         Tips:这里进行重写时,用到 super.父类成员方法,表示调用父类的成员方法。

        b、注意事项

      •  子类方法覆盖父类方法,返回值类型,函数名和参数列表都要一模一样。
      •     子类方法覆盖父类方法,必须要保证权限【大于等于】父类权限。(public > protected > (default) > private)
      •     子类方法的返回值必须【小于等于】父类方法的返回值范围。(java.lang.Object类是所有类的公共最高父类)

五、继承后的特点——构造方法

  当类之间产生了关系,现在来讨论各类中的构造方法的影响。

    构造方法的定义格式和作用:

    1、构造方法的名字和类名一致的,所以子类是无法继承父类构造方法的。

    2、构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化工作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。

  Demo:

 1 class Fu {
 2     private int n;
 3     Fu(){
 4         System.out.println("Fu()");
 5     }
 6 }
 7 class Zi extends Fu {
 8     Zi(){
 9         // super(),调用父类构造方法,默认就给提供一个。
10         super();
11         System.out.println("Zi()");
12     }
13 }
14 public class ExtendsDemo07{
15     public static void main (String args[]){
16         Zi zi = new Zi();
17     }
18 }
19 输出结果:
20 Fu()
21 Zi()

    小结:

    •  子类构造方法当中有一个默认隐含的 “super()” 调用,所有一定是先调用的父类构造,后执行的子类构造;
    •    子类构造可以通过super关键字来调用父类重载构造;
    •    super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造,只能有一个。

六、super 和 this

  1、父类空间优于子类对象产生

    在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。

   目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。

      代码体现在子类的构造方法调用时,一定先调用父类的构造方法。

   图示:

 

 

  2、super 和 this 的含义

    •  super:代表父类的存储空间标识(可以理解为父亲的引用)。
    •    this:代表当前对象的引用(谁调用就代表谁)。

  3、super 和 this 的用法

    a、访问成员

this.成员变量      ‐‐ 本类的
super.成员变量     ‐‐ 父类的

this.成员方法名()  ‐‐ 本类的
super.成员方法名() ‐‐ 父类的

      Demo:

 1 class Animal {
 2     public void eat() {
 3         System.out.println("animal : eat");
 4     }
 5 }
 6 
 7 class Cat extends Animal {
 8     public void eat() {
 9         System.out.println("cat : eat");
10     } 
11     public void eatTest() {
12         this.eat(); // this 调用本类的方法
13         super.eat(); // super 调用父类的方法
14     }
15 }
16 public class ExtendsDemo08 {
17     public static void main(String[] args) {
18         Animal a = new Animal();
19         a.eat();
20         Cat c = new Cat();
21         c.eatTest();
22     }
23 } 
24 输出结果为:
25 animal : eat
26 cat : eat
27 animal : eat
View Code

 

    b、访问构造方法

this(...)  ‐‐ 本类的构造方法
super(...) ‐‐ 父类的构造方法

    注意:子类的每个构造方法中均有默认的 super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()

      super() this() 都必须是在构造方法的第一行,所以不能同时出现

七、继承的特点

  1、Java 只支持单继承,不支持多继承。

    Demo:

1 //一个类只能有一个父类,不可以有多个父类。
2 class C extends A{}         //ok
3 class C extends A,B...     //error

  2、Java 支持多层继承(继承体系)。

    Demo:

1 class A{}
2 class B extends A{}
3 class C extends B{}

   扩展:顶层父类是 Object 类,所有的类默认继承 Object,作为父类。

  3、子类和父类是一种相对的概念。

图示:

 

转载于:https://www.cnblogs.com/niujifei/p/11354812.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值