面向对象--->封装和继承

封装
封装指在实际实现时,将复杂的内部结构隐藏起来,并为这组复杂
的结构取一个统一的名称进行使用。在现实世界中,大量的存在封装的例子,例
如电脑的硬盘,将多组复杂的线路和存储信息的磁片封装起来,并将该组结构取
名为硬盘,以后就可以使用硬盘来代表该结构,而不需要更多的了解内部的信息。
在面向对象技术中,类是典型的封装性的体现,类将一组属性和功能
组合成一个统一的结构,并使用类名来代表该结构。
封装性的最大优势在于隐藏每个类的内部实现(内部结构),从而既方
便项目的分解也降低了项目的难度。
例如以设计汽车为例,我们可以把汽车看作是软件开发中的整个项目,
在实际设计时,首先可以将设计汽车分解为设计汽车的每个组件,然后具体对每
个组件进行设计,而组件和组件的设计之间关联性很小,例如设计发动机的设计
小组不需要很详细的了解轮胎设计小组的工作。而这里的每个组件可以看作实际
面向对象设计中的类,每个类都把自己的内部实现隐藏起来,只通过名称使其它
类了解该类的作用,并开放一些基本的功能供其它的类使用即可。
这样可以在实际设计时,每个类都更注重自身的实现,而对于其它类
的实现不需要深入了解,这样可以在总体上降低交流的频率,从而降低整个项目
的复杂度。
通常情况下,一般把类和类之间的关联性又称作耦合性,类和类之间
的关联性比较低也称作耦合性比较低。在实际设计项目时,低耦合的项目是程序
设计人员设计系统的目标之一。


继承
在我们认知现实世界时,一般会把事物进行分类,而每一类内部又划
分出很多的小类,生物学中将该方式体现的很彻底。例如猩猩属于动物中的哺乳
类灵长目,这里的动物、哺乳类和灵长目都是一个特定的类别,和以前不同的是
这些类别之间存在包含关系(is-a),换句话说,也就是哺乳类是动物类的一种,
灵长目是哺乳类的一种。
其实在程序设计中,很多设计出来的类也存在这样的包含关系,这样
一个类的内部会包含和其它类类似的特征和属性,如果在设计时可以以另外一个
类为基础进行设计,那将是多么激动人心的特性,这个特性就是面向对象设计中
的继承性。
在一个项目中,如果类和类之间存储包含关系,即一个类是另外一个
类的一种,就可以使用继承。
继承性提供了全新的类设计方式,可以充分利用了已有类内部的结构
和功能,极大的降低了类内部的代码重复,是设计类的一种显著的变革,对于大
型的项目设计十分有用。另外很多技术的应用中也包含大量的继承成分,使整个
技术体系比较固定。


继承语法
在 Java 语言中,继承的语法格式比较简单,如下所述:
访问控制符 [修饰符] class 类名 extends 父类名{
……
}
在声明类时,声明该类的继承关系,使用 extends 关键字实现,其中
extends 关键字前面是声明出的新类名,extends 关键字后面的类名是被继承的
类名,要求被继承的类名已存在。Java 语言采用的是单重继承,也就是说一个
类只能有一个直接父类。在类声明时,如果没有使用 extends 关键字声明父类,
则自动继承 Object 类。说明:Object 类是系统提供的类,该类已存在。
示例代码如下:
//Animal.java
public class Animal {
/**类型名称*/
String name;
/**移动方式*/
int moveType;
}
//Mammalia.java
public class Mammalia extends Animal{
/**哺育时间*/
int fosterTime;
}
这里 Mammalia 类就是 Animal 类的子类,Animal 类就是 Mammalia 类
的父类,子类和父类具有相对性,正如一个祖孙三代的家庭内部,每个人相对于
不同的人扮演不同的角色一样。同时类和类之间的继承具备传递性,就如现实中
的血缘关系一样。

继承说明
两个类之间如果存在了继承关系以后,将带来哪些不同呢?下面依次来
进行说明:
l 子类拥有父类的所有属性
子类中继承父类中所有的属性,在父类中声明的属性在子类内部可以直接调用。
说明:如果访问控制符限制则无法访问。
l 子类拥有父类的所有方法
子类中继承父类中所有的方法,在父类中声明的方法在子类内部可以直接调用。
说明:如果访问控制符限制则无法访问。
l 子类不拥有父类的构造方法
子类不继承父类的构造方法,如果需要在子类内部使用和父类传入参数一样的构
造方法,则需要在子类内部重新声明这些构造方法。
l 子类类型是父类类型
子类类型的对象可以自动转换为父类类型的对象,父类类型的对象则需要强制转
换为子类的对象,转换的语法个基本数据类型转换的语法相同。

继承()
方法覆盖
前面介绍了继承的一些基础知识,现在介绍一些在使用继承时需要注
意的问题。熟悉这些问题将更好的解决项目中的实际问题。
例如在实际的游戏中,会按照怪物的种类实现设计。首先设计一个基
础类 Monster,然后按照怪物类别设计 Monster 的子类,如 Boss、NormalMonster
等。则在实际实现时,每个怪物都有移动(move)的功能,但是在 Boss 和
NormalMonster 的移动规则存在不同。这样就需要在子类的内部重新编写移动的
功能,从而满足实际的移动要求。该示例的实现代码如下:
//Monster.java
public class Monster{
public void move(){
//移动功能
}
}
//Boss.java
public class Boss extends Monster{
public void move(){
//Boss 类的移动规则
}
}
//NormalMonster.java
public class NormalMonster extends Monster{
public void move(){
// NormalMonster 类的移动规则
}
}
这样在 Monster 的每个子类内部都重新书写了 move 方法的功能,这种
在子类内部重新父类中的方法的语法现象,称作方法覆盖(override)。
方法覆盖在实际中保持了类的结构的统一,在实际使用时将极大的方
便程序开发人员的使用,使项目的整体结构保持统一,便于项目的维护。
在使用子类的对象时,子类内部的方法将覆盖从父类继承过来的方法,
也就是说子类的对象调用的是子类的功能方法,而不是父类的方法。
在进行方法覆盖时,子类内部的方法和父类的方法声明相同,而且子
类方法的限制不能比父类的方法严格。例如不能使用比父类限制更大的访问控制
符或抛出比父类更多的异常等,这个在实际使用方法覆盖时需要特别的注意。
在实际的项目中大量的存在需要在子类内部重写父类的功能方法的地
方,恰当的使用方法覆盖将为项目开发带来很大的便利。


需要注意的问题
除了方法覆盖以外,在实际使用继承时还有很多需要注意的问题。下
面就这些问题进行一一说明。
1、 属性覆盖没有必要
方法覆盖可以重写对应的功能,在实际继承时在语法上也支持属性覆盖(在子类
内部声明和父类属性名相同的属性),但是在实际使用时修改属性的类型将导致
类结构的混乱,所以在继承时不能使用属性覆盖。
2、 子类构造方法的书写
该项是继承时书写子类最需要注意的问题。在子类的构造方法内部必须调用父类
的构造方法,为了方便程序员进行开发,如果在子类内部不书写调用父类构造方
法的代码时,则子类构造方法将自动调用父类的默认构造方法。而如果父类不存
在默认构造方法时,则必须在子类内部使用 super 关键字手动调用,关于 super
关键字的使用将在后续进行详细的介绍。
说明:子类构造方法的参数列表和父类构造方法的参数列表不必完全相同。
3、 子类的构造过程
在构造子类时由于需要父类的构造方法,所以实际构造子类的过程就显得比较复
杂了。其实在实际执行时,子类的构造过程遵循:首先构造父类的结构,其次构
造子类的结构,无论构造父类还是子类的结构,都是首先初始化属性,其次执行
构造方法。则子类的构造过程具体如下:
如果类 A 是类 B 的父类,则类 B 的对象构造的顺序如下:
a) 类 A 的属性初始化
b) 类 A 的构造方法
c) 类 B 的属性

d)类B的构造方法

由于任何一个类都直接或间接的继承自Objeck类,所以Objeck类的属性和方法都是首先执行的。
4
、 不要滥用继承

在实际的项目设计中,继承虽然很经常使用,但是还是不能滥用,使用继承的场
合以及相关问题参看下面的说明。


如何设计继承
在实际的项目中,类和类之间的关系主要有三种:
1、 没有关系
项目中的两个类之间没有关联,不需要进行消息传递,则这两个类之间就没有关
系,可以互相进行独立的设计。
2、 使用关系(has-a)
如果一个类的对象是另外一个类的属性,则这两个类之间的关系是使用关系。例
如把房屋(House)看作是一个类,把门(Door)看成另外一个类,则房屋有一个门,
代码的实现如下:
//House.java
public class House{
public Door door;
}
//Door.java
public class Door{
}
则这里 Door 的对象是 House 类的属性,则 Door 和 House 类之间的关系就是使用
关系,House 使用 Door 类来制作自身。
使用关系提供了使用已有类来声明新类的方式,可以以组合的方式来构建更复杂
的类,这是项目中使用类的常见方式之一。
判断是否是使用关系的依据就是:has-a,一个类具备另外一个类的对象,例如
一个 House 有一个门。
3、 继承关系(is-a)
如果一个类是另外一个类的一种,也就是在分类上存在包含关系,则应该使用继
承来实现。例如 Boss 是怪物的一种,则使 Boss 继承 Monster 类。
下面简单介绍一些项目中继承的设计方法。在实际设计继承时,一般
有两种设计的方法:
1、 自上而下的设计
在实际设计时,考虑类的体系结构,先设计父类,然后根据需要来增加子类,并
在子类的内部实现或添加对应的方法。
2、 自下而上的设计
在实际设计时,首先不考虑类的关系,每个类都分开设计,然后从相关的类中把
重复的属性和方法抽象出来形成父类。
对于初学者来说,第二种设计方式相对来说比较容易实现,所以一般
初学者都按照第二种设计方式进行设计,设计完成以后再实现成具体的代码

原文地址:https://www.cnblogs.com/bocai2010000/p/6744901.html