Java面向对象编程三大特征 - 继承
写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域,如今终有小成,愿将昔日所获与大家交流一二,希望对学习路上的你有所助益。同时,博主也想通过此次尝试打造一个完善的技术图书馆,任何与文章技术点有关的异常、错误、注意事项均会在末尾列出,欢迎大家通过各种方式提供素材。
- 对于文章中出现的任何错误请大家批评指出,一定及时修改。
- 有任何想要讨论和学习的问题可联系我:zhuyc@vip.163.com。
- 发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。
Java面向对象编程三大特征 - 继承
本文关键字:Java、面向对象、三大特征、继承
文章目录
- Java面向对象编程三大特征 - 继承
- 一、思想解读
- 1. 什么是继承
- 2. 继承有什么用
- 3. 继承的限制与规则
- 4. 如何设计子父类
- 二、子父类的使用
- 1. 权限修饰符
- 2. this与super
- 3. final修饰符
- 4. 终极父类:Object
继承是面向对象编程的三大特征之一,继承将面向对象的编程思想体现的更加淋漓尽致,允许类和类之间产生关联,对于类和对象的基本知识可进传送门: Java中的基本操作单元 - 类和对象。
一、思想解读
1. 什么是继承
从类的概念出发,我们可以通过定义class去描述一类事物,具有相同的属性和行为。但在很多时候我们希望对类的定义能够进一步细化,这就相当于是一个大的分类下面有很多的子分类,如文具下面可以分为:写字笔、便签、文件管理等等。
如果品类更加的复杂,可以先分为:学生文具、办公文具、财会用品,然后在每个品类下面再根据具体的作用去划分。这些被划分出来的子类别都一定具有父类别的某些共同特征或用途,并且有可能存在多级的分类关系,那么如果我们使用面向对象的语言去描述出这样一种关系就可以使用继承。
下面我们将例子与面向对象中的概念进行对应:
- 上述关系可以用子类别继承自父类别来描述
- 父类别被称作父类或超类
- 子类别被称作子类
- 继承可以使子类具有父类的各种属性和方法,不需要再次编写相同的代码
2. 继承有什么用
如果我们将学生类进一步细化为:初中生、高中生、大学生。显然,细化之后的类与类之间一定是存在某些差异的,但是也一定会存在共同点。如果我们使用代码进行表示,三个类中会有很多相同的属性或方法,也会存在一些差异:
// 定义类:初中生
public class JuniorStudent{// 相同的属性public String name;public int age;public String school;public String grade;// 其他方法
}
// 定义类:高中生
public class SeniorStudent{// 相同的属性public String name;public int age;public String school; public String grade;// 不同的属性public String subject;// 科目:文理科// 其他方法
}
// 定义类:大学生
public class UniversityStudent{// 相同的属性public String name;public int age;public String school;public String grade;// 不同的属性public String college;// 学院public String major;// 专业// 其他方法
}
上面只是列举了部分的属性,可以发现有很多属性是完全重合的,方法也有可能存在相同的现象。这个时候我们就们就可以将其中相同的属性和方法抽取出来,定义一个Student学生类,从而对每个类进行简化。
// 定义类:学生
public class Student{// 提取公共的属性public String name;public int age;public String school;public String grade;// 提取公共的方法
}
// 简化后的初中生
public class JuniorStudent extends Student{// 其他方法
}
// 简化后的高中生
public class SeniorStudent extends Student{// 不同的属性public String subject;// 科目:文理科// 其他方法
}
// 简化后的大学生
public class UniversityStudent extends Student{// 不同的属性public String college;// 学院public String major;// 专业// 其他方法
}
// 定义测试类
public class Test{public static void main(String[] args){JuniorStudent juniorStudent = new JuniorStudent();juniorStudent.name = "小明";// 正常使用,来自父类SeniorStudent seniorStudent = new SeniorStudent();seniorStudent.name = "小李";// 正常使用,来自父类seniorStudent.subject = "文科";// 自有属性,来自子类UniversityStudent universityStudent = new UniversityStudent();universityStudent.name = "小陈";// 正常使用,来自父类universityStudent.college = "XX大学";// 自有属性,来自子类universityStudent.major = "XX专业";// 自有属性,来自子类}
}
从上面的例子可以看出,子父类之间可以通过extends关键字建立继承关系。子类可以直接使用父类中定义的属性和方法,也可以覆盖父类中的方法,表现出子类自己的特点。使用继承有以下几个好处:
- 减少代码量,子类可以继承父类的属性和方法
- 提高复用性,便于维护
- 子类可以通过覆盖父类的方法表达自身的特点
- 可以使类和类之间产生关联,是多态的前提
3. 继承的限制与规则
在Java中,继承的使用存在一些限制,我们需要先明确使用规则才能更好的去设计子父类。一言以蔽之:Java不支持多继承,但支持多重继承(多级继承),从一个子类出发,只存在一条路找到最终的父类。
- 单继承
class A{...
}
class B extends A{...
}
- 多重继承
class A{...
}
class B extends A{...
}
class C extends B{...
}
- 多子类继承同一父类
class A{...
}
class B extends A{...
}
class C extends A{...
}
4. 如何设计子父类
当我们需要通过程序去描述某一个场景或实现某一个应用系统时,就需要构建很多相关的类,合理的使用继承可以使代码更加高效也更加利于维护。那么子父类的构建就可以从类本身所代表的意义出发,如果含义相似或相近,并且类与类之间没有较大的冲突,那么我们就可以把他们归为一类。另外一种情况就是原有构建的类不能满足新功能的需要,需要据此改进,那么我们就可以将原有类作为父类,扩充出他的子类,使整体的功能更加强大,同时又不会对已有的代码产生较大的影响。
- 从多个相关联的类中提取出父类
可以从管理员(AdminUser)、普通用户(NormalUser)、VIP用户(VIPUser)中提取相同的特征,得到父类:用户(User),同样具有用户名,密码,昵称等信息,同样存在登录方法,只不过各自的实现会有所不同。我们也可以混合使用多种继承方式,得到如下的类关系:
- 从一个已有的类中扩充出子类
对于一个简单的电商场景,产品类的设计会比较简单,只需要标识基本信息和价格即可。如果此时需要举行一个秒杀活动,要在购买页面中标识出原价、特价、活动时间、活动介绍等等信息,这就使得我们要对产品类做出升级,如果直接去修改产品类,会导致出现一些可能不会经常使用的属性和方法,因为这些属性和方法纯粹是为特价商品而设计的。比较好的做法是将原有的商品类(Product)作为父类,然后扩充出它的子类:特价商品类(SpecialProduct),在特价商品类中存放新出现的信息。
- 子类是父类的一个扩充和扩展,使用extends关键字来表示真的是很恰当
二、子父类的使用
理解了相关的概念后,我们回到Java的语法中来,子父类间通过extends来建立继承关系,结构如下:
// 定义父类
public class Father{...
}
// 定义子类,继承父类
public class Son extends Father{...
}
1. 权限修饰符
在之前的文章中,已经介绍了权限修饰符的用法,不清楚的同学可以进传送门:Java面向对象编程三大特征 - 封装。当两个类建立了继承关系时,虽然父类当中的所有内容均会被子类继承,但是由于存在权限修饰符,无访问权限的属性或方法会被隐藏,无法被调用和访问(实例化子类对象时,父类对象也会一同被实例化,详细过程会在后面的文章中单独说明)。
在子类中可以直接调用父类中被public和protected声明的属性和方法,如果是在测试类中,在进行属性调用时依然会受到权限修饰符的限制,看下面一个例子:
src
└──edu└──sandtower└──bean│ Father.java│ Son.java└──test│ Test.java
以上为实体类与测试类所在的目录结构
- Father实体类所在包:edu.sandtower.bean
- Son实体类为Father的子类,与Father在同一包下
- Test测试类所在包:edu.sandtower.test
package edu.sandtower.bean;public class Father{// 父类中的私有属性private double ownMoney = 2000;// 私房钱// 父类中的受保护属性protected double money = 5000;// 父类中的公开属性public String name = "老李";
}
package edu.sandtower.bean;public class Son extends Father{// 子类中的独有属性...// 测试方法public void test(){Son son = new Son();System.out.println(son.ownMoney);// 编译失败,无法访问私有属性,查看私房钱System.out.println(son.money);// 编译通过,在子类中可以访问protected属性System.out.println(son.name);// 编译通过,可以访问public属性}
}
package edu.sandtower.test;import edu.sandtower.bean.Son;public class Test{public static void main(String[] args){// 在test包中的Test类中创建Son实例Son son = new Son();son.name = "小李";// 编译通过,可以访问自父类继承的公开属性// 编译失败,在测试类中无法访问protected属性,因为Test类与Father类并无子父类关系son.money -= 500.0;// 对于Son的其他属性和Father的使用可以自行进行测试,不再赘述}
}
从上面的例子可以看到,权限修饰符所起的作用还是很大的。测试类对于子父类来说是一个处在不同包中的完全无关的类,在调用时会被权限修饰符所限制,所以这里也再度明确一下:权限修饰符是根据类的所在路径与类之间的结构关系进行限定的,不是说在任意一个地方使用子类实例都能调用出父类中的属性和方法。
2. this与super
明确了权限修饰符的作用规则后就带来了一个问题,既然在其他类中不能够访问某些属性,那应该如何赋值和使用呢?这时就可以使用封装的办法,同时结合this和super的使用来解决。
- this:指代当前对象,可以调用当前类中的属性和方法
- super:指代父类对象,可以调用父类中可访问的属性和方法,包括被子类覆盖重写的方法
在使用子类实例时,如果我们想要使用某些父类的属性或方法,可以借助构造器和封装方法。将代码修改后,得到如下结果:
package edu.sandtower.bean;public class Father{// 父类中的私有属性private double ownMoney = 2000;// 私房钱// 父类中的受保护属性protected double money = 5000;// 父类中的公开属性public String name = "老李";
}
package edu.sandtower.bean;public class Son extends Father{// 子类中的独有属性...// 使用构造器为属性赋值public Son(String name,double money){super.name = name;super.money = money;}// 使用封装方法操作父类中的属性public void setMoney(double money){super.money = money;}public double getMoney(){return super.money;}
}
package edu.sandtower.test;import edu.sandtower.bean.Son;public class Test{public static void main(String[] args){// 在test包中的Test类中创建Son实例Son son = new Son("小李",3000);// 成功为父类继承而来的属性赋值// 以下代码编译通过double money = son.getMoney();System.out.println(money);son.setMoney(money - 500);}
}
3. final修饰符
final修饰符可以用来修饰属性和方法,也可以用来修饰类。
当修饰属性时,如果是基本数据类型,则可看做是定义了一个常量,值一旦被指定则不可变。如果是引用类型,则引用无法发生变化,即:可以修改数组或实例中的属性值,但是引用的指向不能再发生变化,无法再指向其他的实例和数组。
由final修饰的方法被子类继承后不能被重写,有关于继承中子父类方法的关系将在论述多态的文章中详细讨论。
由final修饰的class不能被继承,如果我们把继承关系想象成一棵大树,父类为根,子类为枝的话,那么final class就一定只能做树叶了,因为确认不会有它的子类存在了。
4. 终极父类:Object
在刚接触面向对象时,我们可能就听说过一个类,那就是:Object,好像它无所不能装,大饼夹一切的存在。我们所有定义的class都会隐式的继承Object,即:如果我们的类没有使用extends关键字显示的指定父类,那么会自动认为Object是父类,这一过程是在JVM运行时完成的,所以我们不能通过反编译来进行验证。
Object中提供了特别通用的方法,如:toString,hashCode,equals等等。那么为什么使用Object能装下一切呢?首先就是因为Object类一定是最终父类的存在,换句话说就是树根本根!因为如果一个类显示的指定了另外一个类作为父类,那么他的父类或者父类的父类,一定会在某一级隐式的继承Object。
如果想进一步了解为什么任意类型的对象实例都能使用Object类型的引用接收可以查看另外一篇文章:Java面向对象编程三大特征 - 多态。
扫描下方二维码,加入官方粉丝微信群,可以与我直接交流,还有更多福利哦~
Java面向对象编程三大特征 - 继承相关推荐
- 允许使用抽象类类型 isearchboxinfo 的对象_Java面向对象编程三大特征 - 多态
Java面向对象编程三大特征 - 多态 本文关键字:Java.面向对象.三大特征.多态 多态是面向对象编程的三大特征之一,是面向对象思想的终极体现之一.在理解多态之前需要先掌握继承.重写.父类引用指向 ...
- Day55-每日一道Java面试题-Java 面向对象编程三大特性: 封装 继承 多态
Java 面向对象编程三大特性: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问.但是如果一个类没有 ...
- JS面向对象编程三大特征
JS面向对象编程三大特征 JS面向对象的三大特征为封装.继承.多态.下面分别进行介绍: 封装 封装是指创建一个对象集中保存一个事物的属性与功能 继承 继承是指父亲的成员,孩子无需重复创建就可直接使用. ...
- 对java面向对象的三大特征的理解_Java面向对象的三大特征是什么?
面向对象的三大核心特性简介 面向对象开发模式更有利于人们开拓思维,在具体的开发过程中便于程序的划分,方便程序员分工合作,提高开发效率. 该开发模式之所以使程序设计更加完善和强大,主要是因为面向对象具有 ...
- 面向对象的三大特征继承,封装和多态性
目录 1.封装 2.继承 3.多态 面向对象的三大特征: 1.继承2.封装3.多态性 1.封装 把类中的属性私有化,模块化及信息隐蔽,也就是一个类把自己内部的实现细节进行隐蔽只暴露对外的接口,封装又分 ...
- Java面向对象的三大特征(封装,继承,多态)
一.封装 1.概念 封装是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的. 2.封装原则 将类的某些信息隐藏在类内部,不允许外部程序直接访问, ...
- Java面向对象的三大特征:封装、继承和多态
封装: 封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(成员方法),才能对数据进行操作. 封装--访问控制修饰符(Java提供四种访问控制修饰符) ...
- 面向对象编程三大特征之一 继承
文章目录 继承 概述 语句定义格式 继承的特点 注意事项 继承与成员变量之间的关系 this关键字与super关键字的使用区别 继承与构造方法的关系 继承与成员方法的关系 重写与重载的区别 方法重写的 ...
- java面向对象的三大特征是6_Java面向对象的三大特征
面向对象的本质:以类的方式组织代码,以对象的方式组织数据. 面向对象三大特性:封装 继承 多态 封装: 概念: 隐藏对象内部的复杂性,只对外公开简单的接口.便于外界调用,从而提高系统的可扩展性,可维护 ...
- java五大原则_Java面向对象的三大特征和五大原则
Java面向对象的三大特征 封装 封装(Encapsulation)是指属性私有化,根据需要提供setter和getter方法来访问属性.即隐藏具体属性和实现细节,仅对外开放接口,控制程序中属性的访问 ...
最新文章
- 刻意练习:LeetCode实战 -- 不同的二叉搜索树
- Zookeeper分布式集群部署
- 9012教你如何使用gulp4开发项目脚手架
- CF765F Souvenirs 解题报告
- “约见”面试官系列之常见面试题之第五十三篇之网站的资源优化(建议收藏)
- dbcc dbreindex server sql_DBCC DBREINDEX重建索引提高SQL Server性能
- 大侦探福老师——幽灵Crash谜踪案
- Android图片特效处理之图片叠加
- 深度学习之TensorFlow 第三章基本开发步骤--以逻辑回归拟合二维数据为例(转)
- 词嵌入生成词向量_使用词嵌入创建诗生成器
- 一款上手即用的Java代码混淆工具
- mysql 建数据库命令_新手入门MySQL数据库命令大全
- 好用到叫出声!强烈推荐 10 款 Mac 软件!
- matlab全桥电路设计,全桥变换电路的Matlab仿真及实验装置开发.pdf
- 我把淘宝当副业,一年全款买了房:你看不起的行业,真的很赚钱
- 对接应用宝SDK(YSDK)QQ能登录微信无法登陆的一些解决方法**
- ubuntu18.04 台式机无线网卡TPLink WDN5200H2.0驱动安装
- (转)最优化问题简介
- java手机 上网_手机的浏览器能上网,但手机的JAVA程序不能上网
- zookeeper集群搭建报错日志:Cannot open channel to 3 at election address ecs-db04/192.168.0.4:3888