现实问题中,很多情况是需要多个不同类型的对象协作完成的。像在最简单的问题域 “张三有只叫小黑的狗” 中应该有几个类?
两个,对吧?人类和狗类。人类实例张三拥有姓名属性,狗类小黑实例也拥有姓名属性。再假设一个问题域 “李四用双立人刀切菜” 人类实例李四使用刀类名叫双立人的刀在切菜。再比如 “砂锅更适合炖汤” 当前就出现了锅类,锅的分支下还可以有砂锅、铁锅、平底锅等。但不管是什么类型材质的锅,都是属于锅类的。

对象的 3 种关联关系

从上述的几个场景中,我们可以分析出对象和对象间拥有:

  1. has-a 关系
  2. use-a 关系
  3. is-a 关系

顾名思义:

  • has-a 就是 有一个,指在一个对象内部 “拥有” 另一个对象
  • use-a 就是 用一个,指在一个对象的某个方法中“使用”另一个对象
  • is-a 就是指 是一个,指的是一个对象是另外一种对象的特例

其中 is-a 被归属在继承关系,目前只包含前两种 has-a 和 use-a 关系。

has-a 关系

这是一种很常见的关联关系,就像我们提到过的问题域 “张三有只叫小黑的狗”,张三是一个对象,狗也是一个对象。所以在语法上,has-a 关系就是把一个对象设计为另一个对象的属性。在一个对象内部“拥有”另一个对象。

  1. // Human.java
  2. public class Human {
  3. public String name; // 人名
  4. public Dog pet; // Dog 类型的 pet
  5. public Human(String name, Dog pet) {
  6. this.name = name; // 赋值实例的名字
  7. this.pet = pet; // 赋值实例的宠物
  8. }
  9. public void talk() {
  10. System.out.println("我是" + this.name + "我的小狗是" + this.pet.name);
  11. }
  12. }
  1. // Dog.java
  2. public class Dog {
  3. public String name;
  4. public Dog(String name) {
  5. this.name = name;
  6. }
  7. public void eat() {
  8. System.out.println("汪汪!");
  9. }
  10. }
  1. // TestMain.java
  2. public class TestMain {
  3. public static void main(String[] args) {
  4. Dog xiaohei = new Dog("小黑"); // 创建狗类实例 xiaohei
  5. Human zhangsan = new Human("zhangsan", xiaohei); // 创建人类实例 zhangsan
  6. zhangsan.talk();
  7. xiaohei.eat();
  8. }
  9. }

关联关系,还可以细分为单向关联和双向关联

  • A has B 或 B has A 都属于单向关联
  • A has B 且 B has A 叫作双向关联

把对方设计为自己的属性后,有一个特点在于:在当前对象的所有方法中,都可以访问到关联对象。换句话说,两个对象的生命周期是保持一致的,这就是所谓的你中有我,我是你的一部分。

use-a 关系

这种关系的关联度就要弱一些,从关联关系也能看出来是 “使用XX”。在语法上,是把一个对象设计为另一个对象的某个方法的局部变量。就好比是之前提到过的 “李四在用刀切菜” 不可能将刀设置为李四的属性吧?
该变量可以通过参数传递进这个方法,也可以在方法内部自己 new 出。无论采用哪种方式,都是 use-a 关系。无论是参数还是内部 new ,都是方法内部的局部变量,方法结束局部变量就消失,关系解除。

当程序越来越大,书写的类越来越多,文件们就需要一种结构能够进行存放和管理。于是就有了包的概念去分门别类地管理多个类。包在本质上就是用来专门管理 java 类的文件夹。
创建包的方式:对 src 文件夹右键 - 新建 - 软件包。包的命名规范:全小写。

当一个 java 类被放入到某个包中,有以下特点:

  1. 在该类的最高处要增加一句包声明的代码 package 包名; 例如 package traffic;
  2. 默认情况下,一个 java 类只能访问来自于同包的其他 java 类,如果需要访问其他包的类,需要导入 import 将那个类导入进来。就好比以前导入 Scanner 一样 import java.util.Scanner; 可以使用 import 包名.* 导入某个包下所有的类,但不建议这样做,尽量用哪些导哪些
  3. IDEA 工具中有多个创建包和创建类的方式

通常会在一个包中放所有 main() 方法的 java 类,再在其他包中放各种类。