Java基础——面向对象(二)
提示:本文介绍封装、继承、多态
一、封装
1、封装概述
1.1、为什么需要封装?
我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?
我们使用的电脑,内部有CPU、硬盘、键盘、鼠标等等,每一个部件通过某种连接方式一起工作,但是各个部件之间又是独立的
封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。
面向对象的开发原则要遵循“高内聚、低耦合”,而“高内聚,低耦合”的体现之一:
-
高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
-
低耦合:仅对外暴露少量的方法用于使用
1.2、如何实现封装?
关键字:private
实现封装就是指控制类或成员的可见性范围?这就需要依赖访问控制修饰符,也称为权限修饰符来控制。
权限修饰符:public,protected,缺省,private

2、成员变量(属性)私有化问题
成员变量私有化后,需要提供get()/set()方法才能被外部访问,我们把这种成员变量称之为属性。
2.1、成员变量封装的目的
①隐藏类的实现细节
②让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里面加入控制逻辑,限
制对成员变量的不合理访问。还可以进行数据检查,从而有利于保证对象信息的完整性。
③便于修改,可维护性高。
2.2、基本语法
private 数据类型 变量名 ;
例如:public class Person {
private String name;
private int age;
private boolean marry;
}
2.3、getxxx()/setxxx()方法

测试:

3、IDEA自动生成get/set方法
Alt +Fn +Insert/Alt +Insert之后选择自动生成get/set方法
二、继承
1、什么是继承?
继承有延续(下一代延续上一代的基因、财富)、扩展(下一代和上一代又有所不同)的意思。(例如:子承父业)
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类中无需再定义这些属性和行为,只需要和抽取出来的类构成某种关系。
继承的好处:
-
提高代码的复用性。
-
提高代码的扩展性。
-
表示类与类之间的is-a关系
2、基本语法
关键字:extends
基本格式:
【修饰符】class 父类{
语句;
}
【修饰符】class 子类 extends 父类{
语句;
}
2.1、父类
比如:Animal 可能有Dog、Cat、Pig等那么Animal就是它们的父类

2.2、子类
比如Dog、Cat、Pig就是Animal的子类

测试类:

3、继承的特点
3.1、子类会继承父类
从类的定义来看,类是一类具有相同特性的事物的抽象描述。父类是所有子类共同特征的抽象描述。而实例变量和实例方法就是事物的特征,那么父类中声明的实例变量和实例方法代表子类事物也有这个特征。
3.2、Java只支持单继承

3.3、Java支持多层继承

3.4、一个父类可以同时拥有多个子类

4、IDEA中如何查看继承关系
Ctrl + H
5、父类成员变量私有化
子类虽会继承父类私有(private)的成员变量,但子类不能对继承的私有成员变量直接进行访问,可通过继承的get/set方法进行访问。
6、方法重写(Override)
6.1方法重写
我们说父类的所有方法子类都会继承,但是当某个方法被继承到子类之后,子类觉得父类原来的实现不适合于子类,该怎么办呢?我们可以进行方法重写 (Override:注解)
例如:



6.2、在子类中如何调用父类被重写的方法
super:指向当前对象中父类部分的引用

6.3、IDEA重写方法 && 查看继承关系的快捷键
Ctrl + O:重写方法
Ctrl + H:查看继承关系
6.4、重写方法的要求
(1)必须保证父子类之间重写方法的名称相同。
(2)必须保证父子类之间重写方法的参数列表也完全相同。
(3)子类方法的返回值类型必须【小于等于】父类方法的返回值类型(小于其实就是是它的子类,例如:Student < Person)。
注意:如果返回值类型是基本数据类型和void,那么必须是相同
(4)子类方法的权限必须【大于等于】父类方法的权限修饰符。
注意:public > protected > 缺省 > private
父类私有方法不能重写
跨包的父类缺省的方法也不能重写
6.5方法重载和方法重写的区别
方法重载:在同一个类中,方法名相同,参数列表不同,与权限修饰符,返回值类型无关。
方法重写:发生在父子类中,方法名,参数列表必须相同,权限修饰符大于等于父类,返回值类型,抛出异常范围小于等于父类父,类私有方法不能重写,跨包的父类缺省的方法也不能重写
三、多态
多态是继封装、继承之后,面向对象的第三大特性。
生活中,比如求面积的功能,圆、矩形、三角形实现起来是不一样的。跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。那么此时就会出现各种子类的类型。
1、多态的应用场景
有的时候,我们在设计一个数组、或一个成员变量、或一个方法的形参、返回值类型时,无法确定它具体的类型,只能确定它是某个系列的类型。
案例:
(1)声明一个Dog类,包含public void eat()方法,输出“狗狗啃骨头”
(2)声明一个Cat类,包含public void eat()方法,输出“猫咪吃鱼仔”
(3)声明一个Person类,
-
包含宠物属性
-
包含领养宠物方法 public void adopt(宠物类型 pet)
-
包含喂宠物吃东西的方法 public void feed(),实现为调用宠物对象.eat()方法



2、多态的形式和体现
2.1多态引用
Java规定父类类型的变量可以接收子类类型的对象,这一点从逻辑上也是说得通的。
基本语法:父类类型 变量名 = 子类对象;
父类类型:指子类继承的父类类型,或者实现的父接口类型。
所以说继承是多态的前提
2.2、多态引用的表现
表现:编译时类型与运行时类型不一致,编译时看“父类”,运行时看“子类”。
2.3、多态引用的好处和弊端
弊端:编译时,只能调用父类声明的方法,不能调用子类扩展的方法;
好处:运行时,看“子类”,如果子类重写了方法,一定是执行子类重写的方法体;变量引用的子类对象不同,执行的方法就不同,实现动态绑定。代码编写更灵活、功能更强大,可维护性和扩展性更好了。
2.4、多态演示
让Dog和Cat都继承Pet宠物类。




3、应用多态解决问题
(1)声明变量是父类类型,变量赋值子类对象
-
方法的形参是父类类型,调用方法的实参是子类对象
-
实例变量声明父类类型,实际存储的是子类对象
(2)数组元素是父类类型,元素对象是子类对象
(3)方法返回值类型声明为父类类型,实际返回的是子类对象
4、向上转型与向下转型
首先,一个对象在new的时候创建是哪个类型的对象,它从头至尾都不会变。即这个对象的运行时类型,本质的类型用于不会变。但是,把这个对象赋值给不同类型的变量时,这些变量的编译时类型却不同。
这个和基本数据类型的转换是不同的。基本数据类型是把数据值copy了一份,相当于有两种数据类型的值。而对象的赋值不会产生两个对象。
4.1为什么要类型转换
父类变量接收了子类对象之后,我们就不能调用子类拥有,而父类没有的方法了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做类型转换,使得编译通过
-
向上转型:当左边的变量的类型(父类) > 右边对象/变量的类型(子类),我们就称为向上转型
-
此时,编译时按照左边变量的类型处理,就只能调用父类中有的变量和方法,不能调用子类特有的变量和方法了
-
但是,运行时,仍然是对象本身的类型,所以执行的方法是子类重写的方法体。
-
此时,一定是安全的,而且也是自动完成的
-
-
向下转型:当左边的变量的类型(子类)<右边对象/变量的编译时类型(父类),我们就称为向下转型
-
此时,编译时按照左边变量的类型处理,就可以调用子类特有的变量和方法了
-
但是,运行时,仍然是对象本身的类型
-
不是所有通过编译的向下转型都是正确的,可能会发生ClassCastException,为了安全,可以通过isInstanceof关键字进行判断
-
4.2如何向上转型与向下转型
向上转型:自动完成(用多态创建对象时)
向下转型:(子类类型)分类变量

4.3、instanceof关键字
变量/匿名对象 instanceof 数据类型 (判断左侧对象是否为右侧类型)返回值为Boolean型

更多推荐

所有评论(0)