类的封装继承和多态
日期: 2019-12-20 分类: 跨站数据 309次阅读
类的封装、继承和多态
类的特性:封装性、继承性、多态性 和 抽象性。 Java 单继承 + 接口
类的设计方法:类的封装、继承、多态。抽象原则。
一、类和对象
Java程序设计的基本单位就是类。一个Java程序就是一个类定义,所有的概念都必须封装在类中。
一、类
使用成员变量表示对象的属性和状态数据,使用成员方法表示对数据的操作,成员变量和成员方法都统称为类的成员。
类声明: [修饰符] class 类 <泛型> [extends 父类] [implements 接口列表 ]
<修饰符> 是一些说明类属性的关键字,如public 访问权限、abstract抽象类、final最终类等等。
<泛型>是类的类型参数,带参数的类称为泛型类。泛型参数类型是类。写在一对<>中。
声明变量和成员方法
变量 [修饰符] 数据类型 变量 [ = 表达式 ]
方法 [修饰符] 返回值类型 方法([参数列表])[throws 异常类列表 ] { 语句序列 [return [ 返回值 ] ] }
<修饰符>是一些说明成员属性的关键字,包括访问权限 public、protected、private 以及静态成员 static 、最终方法和最终变量 final 等。
成员方法重载
类中的成员不能有二义性,成员变量不能同名,但成员方法与成员变量可以同名;
类中可以有多个同名的成员方法,前提是参数列表不同。称为类的成员方法的重载 ,从在多个方法为一种功能提供多种实现。重载方法之间必须以不同的参数列表(数据类型、参数个数、参数次序)来区分。编译时会根据实际的参数列表类型来确定执行重载方法中的哪一个。如果两个方法名称参数列表相同,则不是重载,是编译错误 。
Java 不支持为形参 设置默认值(默认参数)以下语法错误:
viod set(int y = 1, int x = 2) // 语法错误
二、 对象
类是一种数据类型,声明了一种类就声明了一种数据类型。类的实例是类的取值,对象就是类的变量,一个对象能引用一个实例。----使用对象的过程:线声明对象所属的类,动态申请创建一个指定类的实例,并使对象引用该实例,再访问对象的成员变量,调用对象的成员方法。
声明对象 :语法与声明变量格式相同 → 类 对象
String str; //声明str 是String类的一个对象。
构造实例 :使用 new 运算符可以调用类的一个构造方法。创建该类的一个实例,为实例分配内存空间并初始化。再将该实例赋值给一个对象;
str = new String(); //创建String的一个实例赋值给对象 str
引用成员变量和调用成员方法 :获得一个实例后 可以使用 “ . ” 运算符引用成员变量和调用成员方法。
对象.成员变量; 对象 .成员方法(参数列表);
引用对象模型 :类是引用数据类型,一个对象引用一个实例,含义为对象保存该实例的引用信息,包括首地址存储单元的存储结构。对象之间的赋值是引用赋值。传递的值是对象引用,使得两个对象引用同一个实例,没有创建新的实例。
二、类的封装性(提供模块化的设计机制)
封装是面向对象的核心特性,是信息隐藏思想的具体实现技术。
双层含义 :
1:将数据核对数据的操作包装成一个对象类型,使对象成为包含一组属性和操作的运行单位。
2:实现信息隐蔽,要尽可能地隐藏类中某些数据和实现细节,以约束外部可见性。
使用和设计分离 :使用者知道 做什么、有哪些类、每个类的特点,每个类提供了哪些常量和成员方法等。设计者要知道 怎么做、类怎样定义、类中有哪些数据和方法、它们的访问控制权限。方法如何实现等问题。
Java提供构造方法、析构方法、方法重载、设置访问权限控制等措施对类进行封装。
一、构造与析构
构造方法 :
用于创建类的一个实例并对实例成员进行初始化。构造方法与其他成员方法不同的是构造方法与类名同名。构造方法通过 new 运算符调用。
一个类可以声明多个构造方法对成员变量进行不同需求的初始化,构造方法写不需要返回值类型。
public class Mydate{
public Mydate(int y,int m,int d){ // 声明构造方法,初始化成员变量
year = y;
month = m;
day = d;
}
}
Mydate d = new Mydate(2012,10,14); // 使用 new 运算符调用指定类的构造方法 创建实例并初始化从成员变量
默认构造方法 当没有给一个类声明构造方法时Java自动为该类提供一个无参的默认构造方法。对各成员变量按类型进行初始化。
拷贝构造方法 一个类的拷贝钩爪方法是该类型的构造方法,它将创建的实例初始化为形式参数的实例值。实现对象复制功能。
public Mydate(Mydate d){ // 拷贝构造方法 创建新势力,值同参数实例
year = d.year;
month = d.month;
day = d.day;
}
//调用
Mydate d1 = new Mydate(2012,10,1);
Mydate d2 = new Mydate(d1); // 调用拷贝构造方法复制实例
构造方法重载 重载的构造方法提供创建实例时的多种初始化方案。Java根据实际的参数列表确定到底调用哪一个构造方法。
析构方法 类的析构方法,用于释放实例并执行特定的操作。一个类只能有一个 finalize() 方法,不可重载。
声明如下:
public void finalize() // 析构方法
通常 当对象超过它的作用域时,Java将执行对象的析构方法。一个对象也可以调用析构方法释放对象自己。
d.finalize();
Java有自动垃圾回收机制,通常类不需要设计析构方法,如果要在释放对象时执行特定操作,则类可以声明析构方法。
二、对象的引用和运算
1、this引用
Java的每个成员方法都可以使用代词 this 引用该方法的调用对象。
三种用法:
1、指代对象本身 → this
2、访问本类的成员变量和方法 → this.成员变量; this.成员方法([参数列表])
注:当没有与要访问的全局变量相同的局部变量时,this可省略;
3、调用本类重载的构造方法。
注:在构造方法中 this() 必须是第一行语句,不能使用 this 调用当前的构造方法。
2、对象的关系运算与比较相等
基本数据类型:== 、!= , < , > , <= ,>=
引用数据类型( 类 )
1.当两个对象引用自同一实例时,判断它们的实例值(各成员变量值)是否相等, =,!=。
2.判断两个对象是否相等,equals() 方法。
3、instanceof 对象运算符 判断一个对象所引用的实例是否属于指定类。运算结果时 boolean型。
Mydate d = new Mydate();
d instanceof Mydate // 结果是ture,d 时 Mydate
三、访问控制
全局变量是导致软件维护困恼的一个重要因素。Java不支持类之外的全局变量。一个对象中的成员变量和成员方法如果没有限制能被任何其它类访问,软件维护也很困难。
Java 为类 及其成员提供 共有、保护、缺省、和私有等多级访问控制权限。用于声明该类或成员能被其他类访问的范围。实现信息分级隐藏技术。
一个包(package)封装了一组类型提供了这些类型的命名空间,即一个包中各类型具有唯一名称。包中的类可选择是否对外部可见。
1.类的访问控制权限 2种,共有(public)和缺省
public可以被包中所有其它类访问,缺省权限没有修饰符。仅能被当前包(文件夹)的其它类访问。
一个源文件中可以声明多个类但是public修饰的只能有一个。且该类名必须与文件名相同。
// 再Mydate文件夹中
public class Mydate // 共有权限的类
class Mydate_ex // 缺省权限的类
2.类中成员的访问控制权限
一个类中所有成员都可以被本类的代码访问。为了控制其他类的访问,类的成员有4中访问控制权限。
private 声明私有成员(本类的访问权限)、缺省(包访问权限)、protected 声明保护成员(当前类及子类)、public公有成员(所有类都可被访问)
权限修饰符 | 当前类 | 当前包 | 其他包的子类 | 所有类 |
---|---|---|---|---|
private(私有) | √ | |||
缺省 | √ | √ | ||
protected(保护) | √ | √ | √ | |
public(共有) | √ | √ | √ | √ |
public等修饰权限不能用于修饰方法体中的局部变量 因为局部变量的作用域仅限于当前前方法。
3.set() 和 get() 方法存取对象的属性
对象的多个属性,其他类调用成员变量对其赋值虽然没有语法错误,但是会有逻辑错误。因此必须要将属性私有化 后声明get() 和 set() 方法获取属性的值 或 对属性进行赋值
四、静态成员
Java声明的成员分两种,静态成员 和 实例成员。使用关键字 static 声明成员称为静态成员(类成员),否则称为实例成员。实例成员属于对象,前面讨论的成员变量和成员方法都是实例成员。静态成员属于类 即使没有创建实例也可以通过类名访问静态成员变量调用静态成员方法。
注:在类的内部可直接访问静态成员,省略类名。静态成员也可通过对象引用。在静态方法体中,不能访问1实例成员,也不能用 this 引用。
三、类的继承性
继承,实现抽象和共享,构造可复用软件的有效机制最大限度地实现了代码复用。
一、由继承派生类
继承提供在已有类的基础上创建的类。被创建的类自动拥有被继承类的全部成员,被继承的类称为父类或超类 ,通过继承产生的类称为子类或派生类。
使用关键字 extends 声明一个类指定的父类。语法如下:
[修饰符] class 类 <泛型> [extends 父类] [ implements 接口列表]
Java 是 单继承 的,一个类只能有一个父类,却可以有多个子类,子类继承了父类成员,还可以定义自己的成员。
二、继承原则及作用
继承原则:(4条)
1.子类继承父类所有的的成员变量,包括实例成员变量和静态成员变量。
2.子类继承父类除构造方法以外的成员方法。实例成员方法、静态成员方法、析构方法。
3.子类不能继承父构造方法。
4.子类可以增加成员,从新定义父类成员,添加新成员,但不能删除他们。
继承的作用
子类对象即是父类对象,子类拥有父类除构造方法以外的全部成员。使父类特性和功能得以传承和延续。
Java只允许单继承,这些类组成具有层次关系的树状结构,约定该树的根 Object 类
继承是软件复用的重要措施,通常祖先类用于通用功能的设计,后代类用于特定功能的设计。
Object 类
定义对象的基本状态和行为,它没有成员变量,提供一组所有对象的继承方法,包括通用工具方法和支持线程方法。
子类对父类成员的访问权限
1.子类不能访问父类的私有成员(privare)。
2.子类能访问父类的共有成员(public)和保护成员(protected)。
3.子类对父类缺省权限成员的访问控制分两种:1.可以访问当前包中父类的缺省权限成员,不能访问其他包中父类的缺省权限成员。
访问控制权限体现封装的信息隐蔽原则。
三、子类的构造方法
子类继承父类的成员变量,要对这些变量进行初始化,父类的成员变量应调用父类的构造方法进行初始化,如果子类的构造方法没有显示的调用父类的某个构造方法,那么Java会默认调用父类无参的构造方法。 因此一个类通常需要声明无参的构造方法,即使自己不用,也要为子类准备着。
使用 super() 调用父类构造方法。格式如下
super([参数列表])
// 例,super() 调用必须是第一条语句
public Student(String name,Mydate birthday, String speciality) // 构造方法
{
super(name,birthday); // 调用父类指定的构造方法
this.speciality;
}
四、类的多态性
多态是指“ 一种定义,多种实现 ”,面向对象的核心,主要有方法的多态和类型的多态 。方法的多态包含方法的重载和覆盖。为一种功能提供多种实现;类型的多态表现在,子类是一种父亲类型。
一、子类可以重定义父类成员
子类可重新定义从父类继承来的成员。修改或扩充父类方法的功能。使父类成员能适应子类的需求。
子类定义父类成员包括:
1.重新定义父类的成员变量,则隐藏父类的成员变量。
2.重新定义父类的成员方法,如果参数列表和返回值类型均相同,则覆盖 父类的成员方法。如果参数列表不同,则重载父类成员方法
调用被子类覆盖的同名成员方法,语法格式
super.成员变量 // 当子类隐藏父类成员变量时,引用父类同名的成员变量
super.成员方法([参数列表]) // 当父类覆盖父类的成员方法时,调用父类同名的成员方法
静态变量中不能使用 super 引用。
二、类型的多态
1.子类对象即使父类对象 :当创建一个类实例时也隐含地创建了其父类的一个实例,因此子类构造方法必须调用其父类的一个构造方法。
对象运算符 instanceof 判断一个实例是否属于指定类,包括子实例。
new Person() instanceof Person // 结果是 Ture
new Student() instanceof Person // 结果是 Ture 子类对象即是父类对象
new Person() instanceof Student // 结果是 false 父类对象不是子类对象
2.父类对象引用子类子类实例 :表现为父类与子类赋值的相容性,即父类对象能够引用子类实例反之不能。
Person p = new Student(); // 赋值相容 子类对象即是父类对象
Student s = new Person(); // 语法错,语法出错,父类对象不是子类对象
扩展:其他所有类都是 Object 的子类,一个Object对象能够引用任何类型的实例。
Object obj = new Person(); // 父子相容
三、编译时多态和运行时多态
根据何时确定执行多态中的哪一个,多态分为两种编译时多态(编译时能够确定为哪一个)和运行时多态。
方法覆盖表现出两种多态:当对象引用本类中实例时,为编译时多态,否则为运行时多态。
// 编译时多态
Preson p = new Person(); // 对象引用本类实例
p.toString(); //编译时多态,执行Person类的toString()
// 运行时多态
Person p = new Studeng(); // 父类对象引用子类实例
p.toString(); // 执行谁的toString ? 运行时多态 究竟执行了Person类还是String类中的方法,运行时在确定。 如果Student类声明了 toString()则执行Student类中的,否则执行Person中的。
四、多态的方法实现
Object 类声明了toString()和 equse()方法,这些方法被所有类继承。每个类必须覆盖重写Object的 toString() 和 equse() 方法,equse() 和 toString() 方法在各类中表现除运行的多态性。
一个类如果没有 toString() 和 equse() 方法,则会向祖先类溯源,直至 Object 类。
五、类的抽象性
一个抽象数据类型是描述一种特定功能的基本模块。
一、用继承刻画包含关系
用类来描述一种实体的属性和操作实现。实体间的包含关系可以用类的继承关系来刻画。抽象类用于描述抽象概念,Java可以用来声明类的继承特性,包括最终类和抽象类。
二、抽象类
使用关键字 abstract 来声明的类称为抽象类 ,使用 abstract 声明的方法称为抽象方法 ,抽象方法没有具体的方法体,以“ ; ”结束。
public abstract class ClosedFigure{ // 闭合图形抽象类,public再 abstract 之前
public abstract double area(); // 计算面积 抽象方法 以 “ ; ”结束
}
抽象类不能被实例化,不能创建对象。抽象类通常包含抽象方法,也可以不包含,但是包含抽象方法的类必须被声明为抽象类。如果一个类继承一个抽象类,则必须实现父类的所有抽象方法,否则该类必须声明为抽象类
注:构造方法、静态方法不能被声明为抽象方法。
抽象类的作用:抽象类用于描述抽象的概念。抽象方法提供方法声明与方法实现的分离机制。一个抽象方法在多个子类中表现出多态性 ,使子类具有共同的行为能力。
抽象类为子类约定共同的属性,以及秒速共同操作的抽象方法声明,各类给出各自不同的实现,使抽象方法在子类中表现出运行时多态性。
面向对象设计软件系统的普遍规律: 需求分析,建立对象及其关系模型,利用面向对象语言进行实现。设计多个类及其层次关系。
三、最终类
使用关键字 final 声明的类称为最终类,最终类不能被继承 ,即不能有子类。
public final class Math extends Object // 数学类,最终类
public class MyMath extends Math // 语法错,最终类不能被继承
public final class Circle extends Rllipse // 圆类,不可被继承
如果一个类不希望被继承,可声明为最终类。习惯上将 public 放在 final 前。
注意:抽象类不能被声明为最终类。
声明最终方法,最终方法不能被子类覆盖。最终类中包含的都是最终方法。非最终类也可以包含最终发方法。
public class Circle extends Ellipse{ // 非最终类
public final double area() // 最终方法,不能被子类覆盖
}
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
精华推荐