Java-包、封装、继承、多态

包:
带着包名的类名是全限定类名,在相同的包中的类名才可以省略包名。
为了使用方便,可以在某个.java文件的开头显示的import某个类的全限定类名,后面的代码中就可以直接使用类名来进行操作了。当我们需要用到某个类的时候,不需要记住全限定类名,后面的代码中就可以直接使用类名来进行操作了。
import java.util.*;
*表示通配符,把java.util中所有的类都导入了;但一般不推荐这样做,当我们要使用哪个类,就import哪个。因为同一个类名可能在多个包中都被使用,直接import *的话,可能会出现歧义。

import static:静态导入,导入一个包的类中的静态方法和属性 。
一般包名习惯上使用公司域名的倒装形式表示。
例:
域名:baidu.com
包名:com.baidu

封装:管理软件复杂程度的一种重要的方式
软件开发是一个非常复杂的工作,编写的代码也非常复杂,代码太过于复杂,人就理解不了,封装就是一个简单有效的让代码变得简单的方式:
角色主要有两个:
类的设计者(实现者)、类的使用者(调用者)
封装在Java中的体现:访问权限控制(四种)
public:修饰的属性或者方法可以被类外部的代码使用
private:修饰的属性或者方法只能在类的内部使用,不需要用户关注的细节就被隐藏起来了。
default:默认的访问权限控制:一个属性或者方法前面啥都不写,相当于一个包级权限控制;若某个属性或者方法是default级别,相同包里的类可以访问,但其他包中的类就无妨访问,介于public和private中间)
protected:修饰的属性或者方法可以被同包的其他类使用,也可以被不同包中的子类使用(继承)

严格程度排序:private>default>protected<public

继承:降低代码的复杂度,达到更好的代码重用的效果。
实际开发中,经常会发现,代码中有很多相似的概念,这些相似的概念,只是在一些细节上有细微的差异。
子类中会继承父类的属性和方法。
当new一个子类对象的时候,构造子类对象之前会自动构造一个父类对象,通过super的方式来调用到父类的构造方法。

子类虽然继承了父类private成员,但是不能直接访问!
如果子类想访问父类的成员怎么办?
1.把private改成public,但是这种办法破环了封装(类的使用者能查看也能修改)
2.把这个属性提供一个public的getter方法,比第一个方法好(类的使用者能查看但不能修改)
3.把这个属性设置成protected。推荐使用这种方式(类的使用者无法查看也无法修改,只有子类才可以访问)

注意!!! protected访问权限控制比default更宽松
protected修饰的成员也能被同包中的其它类使用(哪怕不是父子关系),如果是其它包来访问的话,就必须是父子关系才可以使用。

1.一个父类可以创建多个子类
一个子类不能有多个父类(但在别的面向对象程序语言中,可能允许一个子类有多个父类,c++,python都支持多继承)
2.子类能够继承父类的所有属性和方法。(继承不代表就能访问)
3.子类中可以通过super关键字来显示指定使用父类的方法或者属性super(name)

super关键字和this有点像
this:表示当前对象的引用
super:表示当前对象对父类对象的引用

super中的很多属性和方法使用this也能访问(super访问的是父亲的版本,this访问的是孩子的版本,有可能也不一样)

继承关键字extends(扩展)也可以把继承理解为对父类的扩展
继承关系比较复杂,滥用继承会导致代码变得很糟糕

使用继承的约束条件:
1.类的继承层数不要太多,一般不要超过三层,使用final关键字来显示指定这个类能不能被继承
2.使用继承的时候,要求父类和子类之间是is-a的关系(只允许单继承:任何一个类,只有一个直接继承的父类)

Java中有一个特殊的类,Object:所有类的老祖宗,无论是标准库中的类还是自己写的类都是直接或者间接继承自Object。(toString就是Object的方法,更优雅的打出一个对象的内容)

组合has-a(经常会和继承相提并论):
从设计层面体现的一种代码组织方式,对应到Java中体现的是对象中包含其他对象,体现的是has-a这样的关系。

多态:一个引用可能表现出多种形态
1.向上转型:使用父类指向子类的对象(UML图中也是习惯把子类画在上面,把子类画在下面)
三种典型的写法:
(1)直接赋值:最直观
(2)作为方法参数:形参是父类引用,实参是子类对象
(3)作为方法返回值
2.动态绑定:如果类中创建一个普通方法,然后再去调用,调用的时候,编译器早在编译阶段就知道调用的方法是哪个(就执行哪个方法的二进制指令),如果在子类和父类中存在同名方法,此时再去调用,此时编译器就不能在编译阶段知道调用哪个方法了,而需要在运行阶段知道调用哪个方法。也就是说,调用一个方法的时候,不能看引用是啥类型,而要看引用指向什么类型的对象。
3.方法重写:
子类和父类具有相同的名字,相同参数的方法,调用这个方法的时候最终执行父类版本还是子类版本取决于引用对应的实际对象类型。(方法重写是Java语法上的约定,动态绑定描述的是JVM底层执行规则,方法重写这样的语法机制是基于动态绑定来实现的

注意:
1.子类对象构造的时候会先调用父类的构造方法来构造父类对象,如果父类对象有默认构造方法(无参数版本),子类的构造方法就没有额外限制。 如果父类对象有特定的构造方法,子类的构造方法就必须显示的调用父类的对应构造方法。
2.方法重载(Overload):描述两个普通方法之间,名字相同、参数不同(和继承没有直接关系),和返回值无关。 方法重写(Override):必须是父类方法和子类方法之间,名字相同、参数也相同、和返回值无关(重写方法的时候一般不要改返回值的类型)

注解:方法重写的时候一般要给子类的方法上加上@Override注解,注解是Java中的一个语法规则。作用:显示的告诉编译器,下面的方法是重写了父类的方法,编译器就可以进行更加严格的校验,重写方法都要加上@Override注解。

区别 重载(overload) 重写(override)
概念 方法名称相同,参数的类型及个数不同 方法名称、返回值类型、参数类型及个数完全相同
范围 一个类 继承关系
限制 没有权限要求 被重写的方法不能拥有比父类更严格的访问控制权限

进一步理解多态:可以把多态当成封装的更进一步:
封装:让类的调用者不必关注类的实现细节,需要知道这个类是什么类型
多态:让类的调用者不但不需要关注类的实现细节,连这个类是什么类型也不需要知道,只要知道这个类具有某个行为即可。

使用多态的好处:
1.类的使用者对类的使用成本进一步降低(不需要知道类型)
2.多态也能够降低代码的圈复杂度

注:圈复杂度:一段代码的复杂程度,代码中存在的情况越多(分支越多,循环越多)越复杂,代码中的if语句,while、for等语句的数量作为圈复杂度。

3.代码的扩展能力更强。

猜你喜欢

转载自blog.csdn.net/weixin_44378053/article/details/105948475
今日推荐