Java基础教程之组合(composition)
作者:junjie 发布时间:2022-08-02 19:12:32
我们已经尝试去定义类。定义类,就是新建了一种类型(type)。有了类,我们接着构造相应类型的对象。更进一步,每个类型还应该有一个清晰的接口(interface),供用户使用。
我们可以在一个新类的定义中使用其他对象。这就是组合(composition)。组合是在Java中实现程序复用(reusibility)的基本手段之一。
组合与"has-a"
一个对象是另一个对象的数据成员。比如我们看之前提到的充电电筒的例子:
一个充电电筒中的电池、LED灯、按钮…… 都可以是一个对象。我们可以定义一个Battery类来定义和产生电池对象。而在充电电筒的类定义中,可以用一个电池对象作为其数据成员,来代表电池部分的状态。
我们下面定义一个Battery类,并用power来表示其电量。一个Battery的可以充电(chargeBattery)和使用(useBattery)。我们在随后的Torch类定义中使用Battery类型的对象作为数据成员:
class Battery
{
public void chargeBattery(double p)
{
if (this.power < 1.) {
this.power = this.power + p;
}
}
public boolean useBattery(double p)
{
if (this.power >= p) {
this.power = this.power - p;
return true;
}
else {
this.power = 0.0;
return false;
}
}
private double power = 0.0;
}
class Torch
{
/**
* 10% power per hour use
* warning when out of power
*/
public void turnOn(int hours)
{
boolean usable;
usable = this.theBattery.useBattery( hours*0.1 );
if (usable != true) {
System.out.println("No more usable, must charge!");
}
}
/**
* 20% power per hour charge
*/
public void charge(int hours)
{
this.theBattery.chargeBattery( hours*0.2 );
}
/**
* composition
*/
private Battery theBattery = new Battery();
}
上面的new为theBattery对象分配内存,不可或缺。
我们定义Battery类。Torch类使用了一个Battery类型的对象(theBattery)来作为数据成员。在Torch的方法中,我们通过操纵theBattery对象的接口,来实现Battery类所提供的功能(functionality)。
我们说,一个Torch对象拥有(has-a)一个Battery对象。上述关系可以表示成:
has-a: 手电有电池 (注意上面的菱形连线)
通过组合,我们可以复用Battery相关的代码。假如我们还有其他使用Battery的类,比如手机,计算器,我们都可以将Battery对象组合进去。这样就不用为每个类单独编写相关功能了。
我们可以增加一个Test类,看看实际效果:
public class Test
{
public static void main(String[] args)
{
Torch aTorch = new Torch();
System.out.println("Charge: 2 hours");
aTorch.charge(2);
System.out.println("First Turn On: 3 hours");
aTorch.turnOn(3);
System.out.println("Second Turn On: 3 hours");
aTorch.turnOn(3);
}
}
上面程序的运行结果:
Charge: 2 hours
First Turn On: 3 hours
Second Turn On: 3 hours
No more usable, must charge!
我们通过组合来使用了电池对象所提供的功能,比如探测电量是否用尽(根据useBattery()的返回值)。
基本类型
在从HelloWorld到面向对象中,我们将int, float, double, boolean等称为基本类型(primitive type),也就是特殊的类。我们可以将一个整数理解称为一个int类型的对象。int类型可以有赋值、加法、减法等操作接口。普通类型可以视作对基本类型的拓展。我们已经见过了基本类型作为数据成员、方法的参数、方法的返回值和方法内部的自动变量。自然的,普通类型的对象,比如Battery和Torch类的对象,也都可以用于这些地方。
C语言中,可用的数据类型(基本上)已经预设好,比如int, float。在Java中,我们除了可以用这些预设的数据类型外,还可以通过类来定制自己想要的数据类型,然后通过组合来使用。但基本类型和普通类型还是有所区别的。基本类型经常被使用,且所占据内存空间不大,所以在Java中,为了效率起见,这些基本类型与普通的类型(也就是自定义的类)的内存管理方式不同。比如,基本类型一旦声明就会被分配内存空间,而普通类型需要使用new关键字来分配内存空间。
Java为每个基本类型提供了相应的普通类型。比如int基本类型对应Integer类型。如果将基本类型的对象转成相应的普通类型变量,所谓的基本类型也就成为了一般意义上的类型(不再有内存管理上的不同)。
这样,我们对Java“一切皆对象”的理念有了更深一步的理解。
总结
组合,has-a
基本类型


猜你喜欢
- 本文实例讲述了Java实现插入排序的方法。分享给大家供大家参考。具体实现方法如下:import java.util.Arrays; /**
- 要想充分发挥ADO.NET的优势,不仅需要全面、深入理解ADO.NET编程模型,及时总结经验、技巧也十分重要。ADO已经有多年的实践经验,A
- 一、ehcahe的介绍EhCache 是一个纯Java的进程内缓存框架,具有高速、精干等特点,是Hibernate中默认的CacheProv
- 原因用Java调用雪球的API,结果返回的是乱码,一番研究后发现是因为返回的数据使用了GZIP压缩,需要先解压才能得到正确数据。思路使用了G
- Android Fragment实现底部通知栏,供大家参考,具体内容如下截图如下:1. 第一步先要创建fragment(动态注册)然后将两个
- 本文实例讲述了C#实现生成所有不重复的组合功能。分享给大家供大家参考,具体如下:给你几个字母,比如(a,b,c,d,e,f),要求生成所有不
- Java 中的内部类这是一个 Java 内部类的简单实现:public class OutterJava { pr
- 本文实例讲述了Android中Matrix用法。分享给大家供大家参考,具体如下:Matrix ,中文里叫矩阵,高等数学里有介绍,在图像处理方
- 这篇文章主要介绍一下如何实现View的3D旋转效果,实现的主要原理就是围绕Y轴旋转,同时在Z轴方面上有一个深入的缩放。演示的demo主要有以
- 知识点:内部存储空间获取总大小和可用大小;sdcard存储空间获取总大小和可用大小;新名词记录{StatFs:描述文件系统信息的类}概览在开
- 引言在开发中有时候经常需要一些Http请求,请求数据,下载内容,也有一些简单的分布式应用直接使用Http请求作为跨应用的交互协议。在Java
- 本文是vhr系列的第十二篇,项目地址 https://github.com/lenve/vhr邮件发送也是一个老生常谈的问题了,代码虽然简单
- 本文实例讲述了Android双击返回键退出程序的实现方法,是Android程序开发中一个非常实用的功能,分享给大家供大家参考之用。具体方法如
- 本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下1.RandomAccessFileRandomAcce
- 一、题目描述题目:模拟一个简单的银行系统,使用两个不同的线程向同一个账户存钱。实现:使用特殊域变量volatile实现同步。二、解题思路创建
- 大家在使用 Intellij IDEA 的时候会经常遇到各种乱码问题,甚是烦扰。栈长也偶尔会用下IDEA,也有一些解决乱码的经验,我给大家总
- mybatis的foreach标签经常用于遍历集合,构建in条件语句或者批量操作语句。下面是foreach标签的各个属性属性描述collec
- 本文实例讲述了C#检查字符串是否是合法URL地址的方法。分享给大家供大家参考。具体实现方法如下:protected string HTTPC
- AbstractDetectingUrlHandlerMapping是通过扫描方式注册Handler,收到请求时由Abstrac
- 实现闹钟运行的效果如下: 通知栏的运行后效果图如下:布局文件(activity_main.xml)<?xml version