- 引入
- 继承的语法
- 继承中两个类的关系
- 引用数据类型的类型转换
- 转换的是什么
- 转换的前提条件
- 转换的具体情况
- 继承的优缺点
- 继承层次
- Java单继承机制
- 继承层次
- protected访问权限
- 回顾访问权限修饰符的四种访问级别
- protected访问权限
- 结论
- protected访问权限存在的意义
- 继承的限制
继承是整个Java面向对象的核心技术,没有继承就没有Java面向对象,也就没有Java语言。
引入
对于在多个类中被重复定义的成员,既然有重复,那就想复用它们。Java中对代码的直接复用通常依赖于方法,但是想要复用类的成员,显然用方法无法实现,那就必须使用Java中的继承机制。Java中的继承,本质上是对类的成员的复用。
继承的语法
Java在定义一个类时,可以显式地直接让它继承另一个类,这就是Java的继承机制,其语法为:
[访问权限修饰符] class 类名 extends 被继承的类{
// 类体
}
语法解释:
-
extends关键字表示继承。
-
被继承的类必须是已经存在的某个类。
-
被继承的类称之为“父类”,继承父类的类称之为“子类”。
-
继承后,子类会得到父类的所有成员。
需要注意的是:这里的成员只考虑普通成员,静态成员实际上不能被继承,构造器也不能。
-
子类继承父类后,可以在得到父类成员的基础上再自定义自己的成员。所以从功能上来说,子类往往比父类更强大,至少不会比父类差。所以,这也正是Java中的继承使用“extends”关键字的含义:子类继承父类,实际上是子类“扩展”了父类。
-
父类中没有的东西,子类继承不来。
继承中两个类的关系
继承中,子类和父类是“is-a”关系,子类“is-a”父类,子类可以看成是一个父类,子类可以当成父类使用。
“is-a”关系的理解
-
从实际代码角度
可以用父类引用指向子类对象,说明子类对象可以当成父类对象去使用,所以子类“is-a”父类。
-
从数据类型的定义的角度
数据类型是:一组数据 + 基于数据的 *** 作
引用数据类型是:成员变量的集合 + 成员方法的集合
子类通过继承父类,得到了父类的所有成员,从数据类型上来说,子类就覆盖了父类的成员,具有了父类的功能,子类可以当作父类去使用,也就是子类“is-a”父类。
-
从直观的逻辑角度
比如学生属于人类,猫属于动物。直接就能看出“is-a”关系。
值得注意的是:这种方式只能应对常见和简单的场景,实际开发中很多时候没有直白的逻辑关系,就需要通过设计文档来了解相关信息。
反过来,父类和子类的关系
父类对于子类没有直接关系,子类往往要比父类功能更强大丰富,父类不能当作子类使用。
使用继承的原则
要使用继承语法,一定要充分考虑父子类是否具有“is-a”关系。虽然继承的本质是复用成员,但是不要单纯的为了复用成员而使用继承,没有“is-a”关系,就不应该使用继承。在实际开发中,需要认真分析程序中类的关系,写入文档,避免出现错误的继承。
引用数据类型的类型转换 转换的是什么
转换的是引用的数据类型,而对象的类型是不可能转换的。
转换的前提条件
前提条件是必须存在继承,而且类型转换必须发生在父子类关系中,如果不是继承关系的两个类发生类型转换,会导致编译报错。
这也反映出继承一个重要的优点:继承打破了引用数据类型的类型限制,有了继承以后,引用数据类型才出现了类型转换。
转换的具体情况
基本数据类型的类型转换
- 自动类型转换: 指的是不需要写额外代码,编译器自动完成类型转换。是一种取值范围“小转大”的转换。
- 强制类型转换: 指的是由程序员手动写代码,强制编译器完成类型转换。是一种取值范围“大转小”的转换。
引用数据类型的类型转换同样分为两大类:
-
自动类型转换: 指的是不需要写额外代码,编译器自动完成类型转换。
- 条件:子类引用转换成父类引用。
- 特殊称呼:从继承的方向来说,子到父,属于“向上转型”。
- 原因:子类“is-a”父类,子类可以当成父类使用。
-
强制类型转换: 指的是由程序员手动写代码,强制编译器完成类型转换。
-
条件:父类引用转换成子类引用。
-
语法:
强转后的引用的类名 对象名 = (强转后的引用的类名)被强转类型的引用名;
-
特殊称呼:从继承的方向来说,父到子,属于“向下转型”。
-
原因:绝大多数情况下,父类都不能当成子类使用。
-
继承的优缺点
优点
- 继承可以复用类的成员,减少代码冗余。
- 继承的出现,更有利于功能的扩展,提升了程序的可维护性,更好地应对需求变更。
- 继承的出现,对于Java的引用类型而言,弱化了类型的约束力,引用数据类型出现了数据类型转换的概念。这其实是Java实现面向对象第三个特征——多态的前提。
缺点
- 子类继承父类必须无条件的接收父类的所有成员,无法在继承时选择不继承某个成员。
- 父类中对成员进行修改,也会严格地体现到每一个子类中,无法选择具体在哪一个子类生效。
由继承的缺点可以引出——方法的重写
子类在继承父类方法时,不可能不继承父类成员方法,但是,子类可以通过某种手段修改父类方法的实现,这称之为方法的覆盖/重写(override)。
如果说继承是面向对象的核心,那么方法的重写就是继承的核心。
继承层次 Java单继承机制
Java中的一个类,在使用extends关键字直接继承某个类时,最多只能继承一个,不能使用extends关键字同时直接继承多个类。即一个类最多只能有一个“直接父类”。
像Java这种,只能由一个直接父类而不能有多个的设计,称之为“单重继承”或“单继承”。而像C++当中,一个类可以直接继承多个类,就称之为“多重继承”或“多继承”。
但Java中实际上有一些手段,可以实现真正意义上的多继承。
继承层次
Java中的一个类虽然只能有一个直接父类,但是直接父类还有直接父类,那么就会存在多个“间接父类”。
于是就有以下几个概念
-
祖先类:处在继承顶层的类。
Object类是Java所有类继承层次中顶层的祖先类,Java中的每个类,都直接或间接地继承了Object类。如果一个类没有直接使用extends关键字直接继承某个类,那么它就隐式继承Object类,Object类就是它的直接父类,隐式继承不用写出。
-
继承层次:由某个祖先类派生出来的所有类的集合叫做继承层次(族谱)。
-
继承链:从某一个子类开始,到其祖先类的路径。
继承层次中需要注意:
- 在一条继承链中,总称呼下游类是上游类的子类,不管隔了几层。没有孙子类或重孙子类的概念。
- 在一条继承链中,下游的类宗室继承上游类的所有成员,不管隔了几层。
- 在一条继承链中,下游类总可以看成一个上游类,存在“is-a”关系。
- 【重要】不在同一条继承链中的类,没有任何关系,Java中没有“兄弟姐妹”类的概念。因为一方面,子类可以自由扩展功能,另一方面,继承来的东西也是可以修改的。
- 【重要】不在同一条继承链中的类,引用数据类型的类型转换也是不能发生的。引用数据类型的转换一定是发生在同一条继承链中。
- 同一条继承链中,从子到父,是向上转型,是自动类型转换。
- 同一条继承链中,从父到子,是向下转型,是强制类型转换。
- 不能循环定义继承。比如A继承B,B继承C,再让C来继承A,这是不行的。
- 继承链理论上可以无限延伸下去,但是一般实际中不会使用到太多层的继承。
protected访问权限 回顾访问权限修饰符的四种访问级别
- private,私有的,最严格,自己类中才能访问。
- package-private,默认的,缺省的访问权限,同包下可用。
- protected,受保护的访问权限,在不同包包下的子类中可以访问。
- public,公共的,不同包下,随便访问。
注:宽松的访问权限级别,总是包含更严格的访问级别。
protected访问权限
在使用受保护的访问权限时,首先要看清楚这个受保护的成员的位置(包位置)
- 只要是同包下,随便访问。
- 不同包下,只要是非子类,都不能访问。
- 不同包下的子类,这是我们关注的重点。
受保护的成员在不同包的子类中的访问情况:
可以访问,但是只能在子类中创建子类自身对象,然后访问子类从父类中继承过来的受保护成员,其他方式皆不可行。
结论
protected修饰的成员,在同类、同包下可以任意访问;如果是非同包下,则必须是在子类中,且必须是创建子类自身对象,才可以访问它继承自父类的protected成员,其他方式创建对象都不可以访问。
protected访问权限存在的意义
由于继承机制的存在,如果类中的某个成员,非常有价值,我们希望这个成员总是被子类使用,但又不会被滥用,使用protected修访问权限就能达到这样的目的。
被protected修饰的成员,在不同包下能够保证该成员能且只能被子类自身所使用,这样就充分保证了子类拥有对自己继承的protected成员最大的权限,在子类中,可以重写从父类继承过来的方法的访问权限和方法体(注意继承的变量是不存在重写的)。
继承的限制
-
父类中的私有成员,能不能被子类继承
继承了,但是没有访问权限,导致子类无法直接访问父类中的私有成员。可以间接的在父类中写一个有访问权限的Getter方法去访问它,子类继承这个Getter就能够访问继承过来的私有成员了。
-
父类中的构造器,能不能被子类继承
构造器是不能被继承的。
-
父类中的静态成员,能不能被子类继承
静态成员不考虑继承,也不是继承。代码中可以用“子类类名.”访问父类静态成员,不过是父子类共用了父类的静态成员。静态成员永远属于类,可以被子类共用,但这不是继承。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)