04 类和方法
1.封装
一个类把属性算法(逻辑处理)封装起来,只留必要的方法(接口)让用户使用,一个类该暴露什么,不该暴露什么,由类的设计者根据需求设计决定的。private属性用户不能直接访问,如果设计者提供相应的接口方法,那么用户可以通过该接口方法访问。
- 面向对象方法的封装特性是一个与其抽象特性密切相关的特性。
- 具体地,封装就是指利用抽象数据类型将数据和基于数据的操作封装在一起
- 数据被保护在抽象数据类型的内部
- 系统的其他部分只有通过包裹在数据外面的被授权的操作,才能够与这个抽象数据类型交流和交互。
- 封装是一种数据隐藏技术,用户只能看到封装界面上的信息,对象内部对用户是不可见的。
- 封装把对象的所有组成部分(包括数据和方法)组合在一起,定义了程序如何引用对象的数据;封装实际上使用方法将类的数据隐藏起来,控制用户对类的数据(域、属性)修改和访问的权限。
- 被封装的对象之间是通过传递消息来进行联系的。一个消息由三部分组成:
- 消息的接受对象
- 接收对象要采取的方法
- 方法需要的参数
在面向对象程序设计中
- 抽象数据类型通过“类”来代表
- 每个类都封装相关的数据和操作
在实际开发过程中
- 类常用来构建系统内部的模块
- 封装特性把类内的数据保护得很严密,模块与模块间仅通过严格控制的界面进行交互
- 使它们之间耦合和交叉大大减少,从而降低了开发过程的复杂性,提高了效率和质量,减少了可能的错误
- 保证程序中数据的完整性和安全性
封装对对象的影响
- 封装就是将对象具有的一些属性和方法通过封装打包到一起,共同体现一个事物的特征。
- 所有信息都存贮在对象中,即其数据及行为都封装在对象中
- 影响对象的唯一方式是执行它所属的类的方法,即执行作用于其上的操作
信息隐藏(information hiding)
将其内部结构从其环境中隐藏起来 如果对对象的数据进行读写,需要将消息传递给相应对象,得到消息的对象调用其相应的方法对其数据进行读写
- 当使用对象时,不必知道对象的属性及行为在内部是如何表示和实现的,只须知道它提供了那些方法(操作)即可
封装的作用
隐藏对象的属性和实现细节,仅对外提供公共访问方式。
- 将变化隔离;
- 便于使用;
由于封装特性把类内的数据保护得很严密,模块与模块间仅通过严格控制的界面进行交互,使它们之间耦合和交叉大大减少,从而降低了开发过程的复杂性,提高了效率和质量,减少了可能的错误
- 提高复用性;
封装使得抽象数据类型对内成为一个结构完整、可自我管理、自我平衡、高度集中的整体;对外则是一个功能明确、接口单一、可在各种合适的环境下都能独立工作的有机的单元。这样的有机单元特别有利于构建、开发大型标准化的应用软件系统
- 提高安全性;
保护类不受到不必要的修改
封装原则
1. 将不需要对外提供的内容都隐藏起来;
2. 将属性隐藏,提供公共方法对其访问。
- 封装,就是隐藏实现细节
- 将属性私有化,提供公有方法访问私有属性
- 通过这些公有方法访问私有属性
封装的实现:
- 修改属性的可见性来限制对属性的访问
- 为每个属性创建一对赋值(setter)方法和取值(getter) 方法,用于对这些属性的访问
- 在setter和getter方法中,加入对属性的存取限制
2. 类
类是对某一类事物的描述,是抽象的、概念上的定义;对象是实际存在的该类事物的每个个体,是类的实例(instance)
什么是类
- 类就是这些具有相同或相似行为或数据结构的对象的共同描述
- 类是若干对象的模板,并且能够描述这些对象内部的构造
- 属于同一个类的对象具有相同数据结构及行为
类的性质
-
类的名标识一个类
-
在同一个系统环境中,类的名能够唯一标识一个类
-
类必须具有一个成员集合
- 属性
- 方法
- 方法的操作接口
- 类的属性的域
- 基本类
- 用户定义的类
- 支持信息隐藏
类的定义
3.关于接口
接口(interface)是向客户保证类的行为方式的一种协定(contract)。
- 一个Java接口是一些方法特征的集合,但没有方法的实现
- 可以使用Java接口标识类型
Java中有一种专供子类来继承的类,这个类就是抽象类。 - 抽象方法:只有方法说明,没有方法体的方法称为抽象方法。
- 抽象类通常包括一个或多个抽象方法,抽象类的子类必须实现其父类定义的每一个抽象方法,除非该子类也是抽象类。
定义抽象类是因为属于同一类的多个子类,在实现某些方法时,会采用不同的实现方式,这时就要采用不同的方法体来定义。
- Java可以创建抽象类,专门用来当做父类。抽象类类似“模板”的作用,其目的是要依据它的格式来修改并创建新的类。
- 抽象类的方法可分为两种,一种是一般的方法,另一种是以abstract关键字为开头的“抽象方法”。“抽象方法”并没有定义处理的方式,而是要保留给由抽象类派生出的新类来定义。
- 抽象类不能直接用来产生对象。
- 接口(interface) 的结构和抽象类非常相似。接口本身也具有数据成员与抽象方法,但它与抽象类有下列两点不同:
- 接口的数据成员必须初始化。
- 接口里的方法必须全部都声明成abstract,也就是说,接口不能像抽象类一样保有一般的方法,而必须全部是“抽象方法”
接口的一个作用:
- 类继承对于重用超类中的代码很有用,而Java只支持单继承,在遇到需要多继承的情况,可通过接口来帮助实现。(多态性)
接口的特点:
- 接口的访问控制修饰符只有public或者缺省。
- 接口类型也可以继承,并且可以多重继承
- java的类层次结构中有一个顶级类Object ,接口没有
- 接口体内只能声明常量字段和抽象方法,并且被隐式声明为public,static,final可写可不写
接口的实现
<访问控制修饰符><修饰符>class 类名[extends 父类名] implements 接口名表{
类体
}
- 实现接口可以是某个类的子类,也可以是父类。
- 一个类可以“实现”多个接口功能,从而实现多继承
- “继承”后的类可以是抽象类也可以是普通类
- 类中实现方法时,必须使用与该抽象方法完全一样的名字、返回类型和参数表,否则,就构成重载了
接口的应用
- 声明多个类必须实现的方法。
- 编程者可以把用于完成特定功能的方法组织成相对独立的集合体—接口。凡是需要实现这种特定功能的类,都必须实现这个接口。
- 利用接口模拟多继承。
- java程序中的类层次结构是树状结构,这种树状结构在处理某些复杂问题时会显得力不从心。
- 接口在保持单继承优点的前提下,使Java程序的类层次结构更加合理,更符合实际情况。
- 只说明对象的编程接口,而不揭示实际的类体。
编译器会自动加上public修饰符
- 接口的结构和抽象类非常相似,它也具有数据成员与抽象方法,但它与抽象类有两点不同:
- 接口的数据成员必须初始化。
- 接口里的方法全部都是abstract。
用接口的特性来打造一个新的类,称为接口的实现(implementation)
-
接口与一般类一样,均可通过扩展的技术来派生出新的接口。原来的接口称为基本接口或父接口;派生出的接口称为派生接口或子接口。通过这种机制,派生接口不仅可以保有父接口的成员,同时也可以加入新的成员以满足实际问题的需要。
-
接口不提供实现
-
接口定义新类型,可以声明变量
-
类的实例可以赋值给接口类型变量
(1)实现接口的类 实例 = new 实现接口的类()
(2)接口 变量 = new 实现接口的类() ;
- 接口变量应该理解为:接口声明一个接口的引用。
- new 实现接口的类();应理解为创建了一个类的实例。
- 将创建的类的实例的地址赋给接口的引用 。
抽象类与接口的比较
不相同的地方:
- 抽象类是对类的抽象。而接口只是一个行为的规范或规定。
- 接口不具备任何继承的特点。它仅仅是承诺该完成的方法。
- 类可以实现多个接口,但只能继承一个父类。
- 在Java中,interface可以同时继承多于一个interface
- 抽象类可以包含方法的实现(非抽象方法),而接口中所有的方法都没有实现。
- 接口是某类行为或功能的抽象,是一种开关或者是契约;抽象类是对具体对象的最高抽象,这个对象拥有自己的最基本特征
飞机会飞,鸟会飞,他们都实现了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类。
4.属性
Delphi,VB,C#包含属性概念。
实际上java中没有属性这个概念,只有字段和方法,但是可以通过私有字段和声明get,set方法来实现类似于C#中属性的效果。(注意,是类似)
字段,通常叫做“数据成员”。
例如:
void setA(String s){} String getA(){}
当一个类中拥有这样一对方法时,我们可以说,这个类中拥有一个可读写的a属性(注意是小写a)。如果去掉了set的方法,则是可读属性,反之亦然。
内部类(嵌套类)
在一个类中定义另外一个类。(Java内部类。C++嵌套类)
- 语义差别:
- Java内部类被连接到外部类的具体实例上,并且允许存取其实例和方法
- C++仅是命名手段,限制和内部类相关的特征可视性
JAVA内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类。
- 内部类是非常有用的特性,因为它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。
- 与组合完全不同。
例子:
class Outer
{
private int size ; //外部类的成员变量
private String thoughts = "My outer thoughts";
class Inner //声明内部类
{
String innerThoughts = "My inner thoughts";
//内部类的成员变量
void doStuff() //内部类的成员方法
{
// inner object has its own "this"
System.out.println( innerThoughts );
// and it also has a kind of "outer this"
// even for private data of outer class
System.out.println(thoughts);
}
}
}
class TestMe
{
public static void main( String args[] )
{
// instantiate me, the outer object
Outer o = new Outer();
// Inner i = new Inner();
// NO! Can't instantiate Inner by itself!
Outer.Inner i = o.new Inner();
// now I have my special inner object
i.doStuff();
// OK to call methods on inner object
}
}
You can also instantiate both the outer class and inner class at the same time:
Outer.Inner i = new Outer().new Inner();
END