本节意在使你理解面向对象的编程范式。
本节学习目标
- 领会面向对象编程范式和结构式编程的不同之处
- 了解对象的关键特性
- 了解源于面向对象程序设计的定义原则的好处
对象是什么?
Java语言是面向对象的。本节扼要介绍面向对象(OOP)的的概念与原则,与结构式编程形成鲜明的对比。
面向对象的语言,遵循结构式编程语言如C或COBOL语言不同的编程模式。结构式编程范式高度面向数据:你要先有数据结构,然后在数据结构中进行编程。想Java一样的面向对象语言结合数据和程序指令为对象。
一个对象是一个独立的实体,包含属性和行为或更多。面向对象语言,数据和变成逻辑是结合在一块的,与之区分的结构式编程,首先具有数据字段的数据结构,会将该结构传递给所有应用逻辑处理程序。这种组合可以发生在不同的粒度级别,从细粒度的对象,如一个数字,粗粒度的对象,如在一个大的银行应用资金转移服务等(This combination can occur at vastly different levels of granularity, from fine-grained objects such as a Number, to coarse-grained objects, such as a FundsTransfer service in a large banking application)。
父、子对象
父对象是一个作为结构基础的对象,衍生出更复杂的子对象。子对象看起来类似父对象,但是子对象更具体,举个例子:车是一个父对象,自行车是一个子对象。在面向对象编程范式下,我们可以重用父对象的通用属性和行为,子对象不同于父对象的属性和行为可以自行添加。例如:车是运输工具、交通工具,一般具有轮子。自行车这个子对象有自己独特的属性、功能:脚踏、骑行,也能运输小件物品。
对象通信与协调
对象之间的通信是发送"消息",在java中可以认为是调用方法。此外,在一个面向对象的应用程序中,程序代码协调对象之间的活动交互,得意在上下文中执行任务。
对象总结
一个编写的很好的对象拥有的特点:
- 定义明确的范围
- 执行有限的活动
- 只知道它的数据和任何其他对象,它需要完成它的活动
示例:一个"人"对象
我的第一个例子基于一个常见的开发场景:一个个体用一个Person
对象表示。
从前面对对象的定义可以知道,一个对象拥有两个最基本的元素:属性和行为。下面体现这些元素如何应用到人的对象中去的。
作为一个经验法则(As a rule of thumb),可以认为对象是名词,行为是动词。
属性(名词)
一个人会有那些属性呢?应该包含以下基本的吧:
- 姓名
- 年龄
- 身高
- 体重
- 眼睛颜色
- 性别
你也许认为还会有更多属性,但是这个列表所列向也是一个很好的开始了。
行为(动词)
一个真实的人可以做各种各样的事(all sorts of things),但对象行为通常涉及到某种类型的应用程序上下文。在商业应用中,你可能会问Person
对象:“什么是你的身体质量指数(体重指数BMI)?” 作为答复,Person
可能使用身高和体重属性计算BMI。
更多的复杂逻辑可能隐藏在Person
对象中,但是现在,假使Person
拥有如下行为:
- 计算BMI
- 打印所有属性
状态和字符串
状态在面向对象中是一个很重要的概念。一个对象的状态在任何时候都是由它的属性的值表示的。
Person
的例子中,他的状态通过属性定义:姓名、年龄、身高和体重等。如果你想展示它的属性列表,你就可以用到String
类了,后面我们会学习更多关于String的内容。
使用状态和字符串一块的概念,你可以对Person
说,“告诉我关于你所有属性的一个列表(或给出一个字符串形式)”
面向对象的原则
如果你拥有使用结构式编程的背景,面向对象的含义可能不太清晰。毕竟,一个人和任何逻辑获取属性(转换)的值可以用C或COBOL等其他语言做到。如果你理解了面向对象的原则:封装性、继承性和多态性,你就会更加清晰的理解OOP了。
封装性
回顾上面提到的关于对象的讨论,这些特点就是工作中封装对象的原则。隐藏是另一个术语,有时用来表示私有的(protected)、受保护的(protected)对象的性质。
不管术语,重要的是,对象保持它的状态和行为和外部世界的边界。像现实世界中的对象,在计算机编程中使用的对象有不同类型的关系,不同类别的对象使用在它们的应用程序中。
在JAVA平台中,你可以使用访问修饰符(public、private、protected、default后面会讲解到)改变对象的性质。public
修饰符表示是公用的,private
是私有的,一般是对象自身使用。
公共/私有边界强制执行面向对象的封装原则。Java平台中,你可以用对象的基础来改变一个物体上的边界的强度,封装是java语言的一个强大的功能。
继承
结构式编程中,通常是复制一个结构体,赋予一个新名字,添加或修改属性去创建一个新实体。这样会产生大量重复的代码,引发更多维护问题。
面向对象使用了继承的概念,通过指定一个类 —— 不需要额外的代码 —— 就能复制它的属性和行为。如果一些属性和行为需要改变,你可以重写他们。被继承的类称之为父类,新的特定的称之为子类。
假设你正在编写一个应用程序并且想使用Person
类作为Employee
的基类(也叫超类)。作为Person
的子类,Employee
拥有所有Person
类的属性,还可以添加额外的属性,例如:
- 纳税人识别号
- 员工编号
- 薪水
继承,创建一个Employee
类更简单了,不需要再手工复制Person
中的代码了。
多态性
多态是一个比封装和继承更难理解的特性。本质上,多态的那些对象可以理解成是继承于同一个分支的,但是在运行时表现不同的行为。
为了理解多态在商用环境是如何应用的,回到Person
的例子。还记得告诉Person
去在一个字符串中格式化它的属性吗?多态使之成为可能,Person
去展示它的属性可以通过不同的方式。你告诉我你的BMI吧,你可能写出来,也可能使用仪器现场测量。。。
多态是java中比较复杂的一个概念,后面会在实例中加深理解。
不是一个纯粹的面向对象的语言
两个性质说明java不是一门纯粹的面向对象语言。第一,java语言混合了对象和原始数据类型(int、long等)。第二,可以暴露一个对象的内部工作细节给另一个使用它的对象。
java语言确实给你必须遵循的原则和产生声音的声音OOP面向对象的代码的工具。因为java不是纯粹面向对象的,你必须通过更多训练编写更好的代码 —— 语言不会强迫你做正确的事,所以你必须自己加强训练。在后面会说明如何编写好的java代码。
测试你的理解内容
单元测试,测试你在本节中掌握的内容。
代码语言:javascript复制1. 一个对象是一个面向数据的实体,任何程序都可以访问该对象的数据
a.是
b.否
c.有时候是
2.下列哪种说法最准确描述父对象、子对象之间的关系?
a.父对象包含和它的子对象的完全相同的代码
b.子对象不关联父对象
c.父对象从子对象中继承属性和方法
d.子对象包含父对象中的代码,但是可以自定义添加额外的属性
3.一个"写得好"的对象的描述应该是:
a.拥有好的访问界定限制,只做某些事情,并且只是自己访问自己的数据
b.大量面向数据的代码可以让任意使用它的对象访问它的属性
c.只让那些使用它的对象识别
d.a和b
e.a和c
f.上面所有的
4.对于对象的属性,下列说法是最好的描述?
a.属性类似于对象的名词
b.属性是对象的行为的描述
c.属性可以表达很多你想让它们表达的意思
d.a和c
e.b和c
f.上面所有的
5.选择可能是Person的属性
a.按周为单位计算年龄
b.兄弟姐妹的数量
c.心率
d.a和c
e.b和c
f.上面所有的
6.对于对象的行为,下列说法是最好的描述?
a.行为是对象的名词
b.行为,类似属性,可以定义在任意地方
c.行为类似对象的动词
d.上面所有的
7.封装意味着"对所有开放",表明对象内部行为完全对外是可见的
a.是
b.否
c.有时候是
8.哪个是对继承的最好描述?
a.一个对象(子)泛化另一个对象的属性和行为
b.子对象继承父对象,添加特定的属性和行为
c.当一个字对象创建的时候,一个众所周知的最好的做法是,开发人员手动复制/粘贴所有的源代码从父对象,以确保代码没破坏
d.当一个子对象继承它的父对象时,只有另外的属性和行为必须编写,这也是OOP的好处之一
e.a和b
f.b和d
g.上面所有的
9.Java是一门纯粹的面向对象的编程语言
a.是
b.否
c.有时候是
答案见下一节。