对象:入门
让我们在本节课中了解对象如何包含其他对象,以及它们之间如何进行通信。
我们之前已经见过创建新对象并把对象作为参数传递给方法的例子。
如果你从未使用过面向对象编程语言,那么你需要先了解一些基本概念。掌握这些之后,你就可以开始编写代码了。
与对象和类的初次接触
我们已经知道,Java 用于创建软件、网页或移动应用程序。它们本质上也是一种软件包。
软件基本上是一组状态和行为的集合。一个软件可能包含成百上千个对象,这些对象以某种方式相互连接,并能够彼此通信,从而让软件正常运行。因此,对象本质上由一些状态和行为组成。
假设一个 Person 对象具有“眼睛颜色”这样的状态,我们可以通过一个行为,比如“佩戴隐形眼镜”,来改变这个状态。
软件中的对象通常用来模拟我们日常生活中看到的真实物体。刚才我们提到了一个 Person 对象。当我们看到现实世界中的一位人物时,我们是否知道这个人物对象背后隐藏了多少状态和行为?这些状态和行为被设计并封装起来,从外部无法轻易猜测。
然而,我们必须有一种机制来清晰地定义这些内容。类的概念在这里起着至关重要的作用。类是创建对象的蓝图或原型。
苏格拉底的故事
你可能听说过苏格拉底的故事,他是古希腊最伟大的哲学家之一,最终被雅典人判处死刑。苏格拉底在临死前饮下了毒药鹤虱(Hemlock)。他在临终时说:“未经审视的人生不值得过。” 从这句话可以看出,他希望通过不断提问来审视人生。但雅典的智者们并不希望如此。
苏格拉底的朋友兼学生柏拉图,同样是伟大的哲学家,记录了他朋友的事迹。事实上,在柏拉图的许多著作中,苏格拉底都是核心人物。接下来,我们将开发一个简单的控制台应用程序,讲述苏格拉底的一生。
在这个程序中,我们将涉及四个对象:Socrates、Plato、雅典的智者们 和 鹤虱。为了创建这些对象,我们需要先为它们编写蓝图。
在下面的程序中,我们将学习如何创建对象,以及如何通过类来定义这些对象的蓝图。
Socrates 类
首先定义 Socrates 类。
1// 苏格拉底类 2// 苏格拉底对象的蓝图 3 4class Socrates { 5 public String name = "苏格拉底"; 6 WiseMen wise; 7 Hemlock hemlock; 8 9 public void questionWiseMen(WiseMen wise){ 10 this.wise = wise; 11 System.out.println(this.name + " 质疑了 " + wise.name + " 的智慧"); 12 } 13 14 public void sayToWiseMen(WiseMen wise){ 15 this.wise = wise; 16 System.out.println(this.name + " 对 " + wise.name + " 说道:" + 17 "‘未经审视的人生不值得过’。"); 18 } 19 20 public void dieByDrinking(Hemlock hemlock){ 21 this.hemlock = hemlock; 22 System.out.println(this.name + " 饮下 " + hemlock.nature + " 死去"); 23 } 24}
Plato 类
接下来,我们需要一个包含一些状态和方法的 Plato 类。
1// 柏拉图类 2// 柏拉图对象的蓝图 3 4class Plato { 5 public String name = "柏拉图"; 6 Socrates socrates; 7 8 public void hasARelationWith(Socrates socrates){ 9 this.socrates = socrates; 10 System.out.println(this.name + " 与 " + socrates.name + " 建立了友谊"); 11 } 12 13 public void writesAbout(Socrates socrates){ 14 this.socrates = socrates; 15 System.out.println(this.name + " 写下了关于他的朋友兼老师 " + socrates.name + " 的故事"); 16 } 17}
WiseMen 类
然后,我们需要定义那些决定苏格拉底命运并判处他死刑的雅典智者们。
1// 智者类 2// 智者对象的蓝图 3 4class WiseMen { 5 public String name = "雅典的智者们"; 6 Socrates socrates; 7 8 public void giveDeathSentenceTo(Socrates socrates){ 9 this.socrates = socrates; 10 System.out.println(this.name + " 对 " + socrates.name + " 判处了死刑"); 11 } 12}
Hemlock 类
Hemlock 对象被定义在一个小类中,其状态被声明为“毒药”。
1// 鹤虱类 2// 鹤虱对象的蓝图 3 4class Hemlock { 5 public String nature = "毒药"; 6}
通过阅读上述蓝图或类,我们可以看出它们基于真实的历史故事。我们编写每个类的方式都包含了某些状态和行为。例如,Socrates 类的状态如下:
1public String name = "苏格拉底";
该类还包含一些行为,例如:
1public void questionWiseMen(WiseMen wise){ 2 this.wise = wise; 3 System.out.println(this.name + " 质疑了 " + wise.name + " 的智慧"); 4}
函数或方法
显然,行为也被称为函数或方法。通过任何方法,我们都可以传递一个或多个参数,比如我们传入了一个 WiseMen 对象,并将其命名为 wise。
现在,不必担心我们使用的关键词,如 public,或语法符号如分号 ; 用于结束语句。这些内容我们稍后会学习。你可能已经注意到,我们总是遵循一套规则来编写类,以便后续可以从中创建一个或多个对象。
我们也注意到,类始终清晰地定义了“状态”和“行为”,以避免产生混淆。计算机不喜欢模糊不清的内容;它需要明确的指令,一步一步的操作手册。
从上面的代码可以看出,一个或多个对象可以是另一个对象的“状态”。看看 Socrates 类:
1public String name = "苏格拉底"; 2WiseMen wise; 3Hemlock hemlock;
main() 方法
这些都是定义在 Socrates 类中的“状态”。在这三个状态中,有两个是“对象”,它们各自拥有自己的类。
最后,我们希望运行这个应用程序,通过创建对象并根据它们之间的关系构建我们的算法:
1// main() 方法代码 2 3public class main { 4 public static void main(String[] args) { 5 Socrates socrates = new Socrates(); 6 WiseMen wiseMenOfAthens = new WiseMen(); 7 Plato plato = new Plato(); 8 Hemlock hemlock = new Hemlock(); 9 10 socrates.questionWiseMen(wiseMenOfAthens); 11 12 wiseMenOfAthens.giveDeathSentenceTo(socrates); 13 14 socrates.sayToWiseMen(wiseMenOfAthens); 15 16 socrates.dieByDrinking(hemlock); 17 18 plato.hasARelationWith(socrates); 19 20 plato.writesAbout(socrates); 21 } 22}
我们希望这个例子能帮助你理解对象如何包含其他对象,并且彼此之间进行通信。这也被称为“拥有关系”(has-a 关系)。当一个类继承自另一个类时,这被称为“是-关系”(is-a 关系)。