Java基础07:重写;重载;内部类;抽象类;接口

关键字:重写;重载;内部类;抽象类;接口

一、继承的概念

    将一些类的共性描述提取出来,单独进行描述,再让这些类与单独描述的这个类有关系即可。

    好处:

    1. 提高代码的复用性

    2. 让类与类之间产生了关系,有了这个关系才有了多态的作用。

    注意:千万不要为了获取其他类的功能,简化代码而继承,必须是类与类之间有所属关系才可以继承。判断条件,父类中的内容是否子类都应该具备。

 

二、继承的特点

    先父类(超类、基类),后子类。Java只支持单继承,不支持多继承。A类继承B类,就不能继承其他类了。因为多继承容易带来安全隐患。多个父类定义了相同功能但功能内容不同时,子类对象不确定要运行哪一个。Java改良了多继承机制,使用另一个体现来完成表示,叫“多实现”。

    Java支持多层继承,就是一个继承体系。

使用继承体系中的功能:想要使用体系,先查阅体系中父类的描述,因为父类中定义的是该体系中共性功能,通过了解共性功能就可以知道该体系的基本功能。这个体系已经可以基本使用。

具体调用时,要创建最子类的对象。原因:一是,有可能父类不能创建对象,如抽象类;二是,创建子类对象可以使用更多的功能,包括基本功能和特有功能。

查阅父类功能,创建子类对象使用功能。

 

聚集关系(包括)

聚合:例如,球队和球员。

组合:例如,手、脚是身体的一部分。

程序反应的是现实中的关系,不一定只有继承。

 

三、 super关键字

子父类出现后,类成员的特点

变量

如果子类中出现非私有的同名成员变量时,子类要访问本类的变量用this,一般可以省略;子类要访问父类中的同名变量用super,不可以省略。super和this的使用几乎一致。this代表子类对象的引用;super代表父类对象的引用。同名变量的情况比较少见,没必要重新定义。

注意,即使父类的成员变量是私有的,也可以继承,只是不能对外访问而已。

使用super继承父类的成员,在堆内存中有两个同名成员,即父类的成员(包括私有的成员)和子类的成员;方法区也是如此。所以用super可以调用父类的成员。加载子类class文件时,先加载父类class文件。

class Zi extends Fu
{
       void show()
       {
              System.out.println(this.num);
       }
}


依然可以运行,子类的堆内存中有父类的num,可以用this访问,也可以用super访问,都指向子类的对象。

 

四、函数覆盖

函数

当子类中出现和父类中一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这也是函数的另一个特性:重写(覆盖)。其实父类的方法还在内存中,只是没有运行而已。

当子类继承了父类、沿袭了父类的功能到子类中,子类虽具备该功能,但功能的内容却和父类不一致,这是没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重新功能的内容。重写一定是有不同的内容,否则无须重新。

开发中,决定不能修改以前的源码!利用继承来扩展程序的功能,重新父类的功能。简化代码可以用super.方法名();

注意:

1. 子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。例如,父类方法为public,子类为默认权限,介于私有和公有之间。

权限:public > 默认 > pirvate

2. 静态只能覆盖静态,不能覆盖非静态,因为没有加载对象。很少用。

3. 父类的方法如果是私有,无法覆盖。因为不能对子类提供,子类不能沿袭这个方法,但可以使用这个方法,相当于新建了一个方法。子类能沿袭,才有覆盖的可能。

4. 子父类中的函数,要么覆盖,要么不能重名,否则无法运行。例如,父类:int show();和子类:void show();

 

重写和重载的比较

 

重载

重写

相同

函数名称一样,内容不一样。

要点

只看同名函数的参数列表

子父类方法要完全一样,包括返回值

否则无法覆盖,也无法运行。

应用

一个类中

子父类中

权限

不影响

子类权限大于等于父类权限

 

五、子类的实例化过程

 构造函数

不能覆盖,因为类名不一样。

在对子类对象进行初始化时,父类的构造函数也会进行,那是因为子类的构造函数默认第一行有一条隐式语句:super(),super()会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super()。注意括号内没有参数。因为空参数的构造函数是默认的,即使父类中不写,子类也可以使用。传什么参数,就调用与之对应的构造函数。

注意:

1. 默认的是super(),空参数的构造函数。

2. 父类中必须有空参数是构造函数,或者默认,或者自己写当父类中只有带参数的构造函数时,子类必须使用super()语句调用父类的构造函数。例如:supet(x).意味子类必须访问父类。

因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问父类中的构造函数。如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。例如。

class Person
{
       private String name;
       Person(String name)
       {
              this.name = name;
       }
       void show() {}
}
 
class Student extends Person
{
       private int age;
       Student(String name)
       {
              super(name);
       }
       Student(String name, int age)
       {
              this(name);
              this.age = age;
       }
       void method()
       {
              super.show();
       }    
}


注意:super语句放在子类构造函数的第一行。

 

子类的实例化过程:

子类中所有的构造函数,默认都会访问父类中空参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式super()。如果父类中没有空参数的构造函数,子类必须手动通过super语句来指定需要访问父类中;当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。如果是this(),指代空参数的构造函数,包含super()。所以,要么this()要么super()。子类中,至少有一个构造函数访问父类中的构造函数。

this和super不能同时出现,因为都只能在第一行。之所以在第一行,是因为需要先做初始化动作。

 

六、 final关键字

final:最终。作为修饰符。

特点如下:

1. 可以修饰类、方法和变量

2. 被final修饰的类不可以被继承。

   继承有利有弊,弊端就是打破了封装性。所以有些类不允许继承,内部的功能不运行复写。要么直接用这个类,要么不用。为了避免被继承、被子类复写功能,用final修饰,最终类。

3. 被final修饰的方法不可以被覆盖。只能另建新方法。强制某些方法不能被覆盖,保证使用。

4. final修饰的变量是一个常量。和static不同,只能被赋值一次,即使再次赋的值一样也不行。既可以修饰成员变量,也可以修饰局部变量(函数中)。

在描述事物的时候,一些数据的出现值是固定的,这时为了增强阅读性,给这些值起个名字,方便阅读。而这个值不需要改变,所以加上final修饰,锁住这个变量。例如,final double PI = 3.14;固定数据,即使出现一次也可以用final修饰。为了方便访问,可以这样:public static final double PI = 3.14;全局常量。

常量的书写规范:所有的字母都大写,如果有多个单词组成,单词间通过“_”连接。

5. 内部类定义在类中的局部位置上时,只能访问被final修饰的局部变量。

类的修饰符有3:public、final、默认。private用来修饰成员。

 

七、 抽象类

   当多个类中出现了相同功能(函数声明)、但功能主体不同,这时也可以进行向上抽取,只抽取功能定义,而不抽取功能主体。例如,void study()。相当于只保留一个壳,壳内的内容由子类定义。

   对于这种表面上看不懂的函数(壳),使用abstract抽象关键字,意为“看不懂”。抽象方法调用没有意义,所以必须存放在抽象类中,也用abstract修饰。不要创建抽象类的对象,没有意义。abstract只能修饰类和方法。

 

   特点:

   1. 抽象方法一定定义在抽象类中。

   2. 抽象方法和抽象类都必须被abstract关键字修饰

   3. 抽象类不可以用new创建对象,虚拟机无法编译。因为调用抽象方法没有意义。但是可以创建引用,例如,Student s。

   4. 抽象类中的方法要被使用,必须由子类复写其所有的抽象方法后,建立子类对象调用,如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。

 

    必须全部复写,只要有一个抽象方法进入子类,子类就变成了抽象类,无法使用。即使空内容复写也可以,例如:void study() {}

    抽象类由不断的分析得到,功能声明一样,但内容不一样,所以只抽取声明,不抽取功能主体。父类只定义基本的功能需求,没有具体内容。具体内容由子类定义,其实是在强迫子类定义功能的内容。

    抽象类中也可以有非抽象方法,子类使用这些方法无需复写。抽象类和普通类没有太大区别,描述事物依然如此,只是有些看不懂的内容(抽象方法),这些看不懂的内容,也是事物的功能,需要明确出现,但无法定义主体,通过抽象方法表示。

子类复写抽象方法,直接使用普通方法。凡是那些功能不确定的方法,都沿袭到子类去做,父类只提供功能声明即可。

抽象类中可以不定义抽象方法,作用仅是不让改类建立对象。使用较少。

 

    抽象类和一般类的比较

 

抽象类

一般类

相同

描述事物的方法依旧,都有一般方法。

不同

出现了看不懂的内容,即抽象方法。

无法定义主体。

有实在内容。内部方法都可以

直接使用,无需复写。

对象

无法建立,不可以实例化,但可以

建立引用。

可以建立对象。

 

八、接口

    格式:interface() {}

    接口的出现将“多继承”通过另一种形式现实,即“多实现”。

    可以理解为一个特殊的抽象类,当类中的方法都是抽象的,该类可以通过接口的形式来表示。接口中的方法都是没有方法体的,便于以后的覆盖。

    class用于定义类,interface用于定义接口。都产生class文件。

    接口定义时的结构特点:

    1. 接口中常见定义:常量和抽象方法

    2. 接口中的成员都有固定修饰符:

      成员常量:例如,public static final int NUM = 3;

      成员函数:例如,public abstract void show();

    接口中的成员都是public的。只要是接口内的成员,public static final abstract这些关键字自动添加,修饰符是固定的。最好写全。不能创建对象

    类与接口之间是“实现”关系,implements。父类中有非抽象内容可以直接拿来用,子类只有将接口中的内容全部实现后才能实例化,否则是抽象类。接口是不可以创建对象的,因为有抽象方法。覆盖接口中的方法必须用public,因为接口中的方法都是共有的。抽象类的权限不确定。

    接口可以被类多实现。一个类可以同时现实多个接口。也是对多继承的不支持的补偿。依然需要覆盖每个接口的方法。即使多个接口有相同名称的方法也没有问题,因为没有方法体,不会产生矛盾,子类可以全部覆盖。

    子类在继承父类的同时,还是实现多个接口。

    类之间是继承关系;类和接口之间是实现关系;接口之间是继承关系;接口之间可以多继承,但是不能有重载函数

 

    接口的特点

    1. 接口是对外暴露的规则。

    2. 接口是程序的功能扩展。体系以外的功能扩展。

    3. 接口可以用来多实现,降低了耦合性。

例如,主板上的插槽就是对外暴露的规则,符合规则的内存条、CPU等都可以插上使用,扩展了主板的功能,同时降低了CPU和主板的关系,即耦合性(紧密联系程度)只要符合就能一起工作,同一个CPU可以插在不同的主板上使用。接口类似这些插槽。模块化开发。

    接口与类之间是实现关系;类可以继承一个类的同时再实现多个接口。

    接口与接口之间是继承关系。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值