作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

我们已经尝试去定义类。定义类,就是新建了一种类型(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快速教程”系列文章

Java基础06 组合的更多相关文章

  1. Java基础06 组合(转载)

    在一个新类的定义中使用其他对象.这就是组合(composition).组合是在Java中实现程序复用(reusibility)的基本手段之一.   组合与"has-a" 一个对象是 ...

  2. java基础06 IO流

    IO用于在设备间进行数据传输的操作. Java IO流类图结构:   IO流分类 字节流: InputStream FileInputStream BufferedInputStream Output ...

  3. java基础06 Java中的递归

      一.递归是指直接或间接地调用自身. 二.递归的注意事项:             A:要有出口,否则就是死递归 B:次数不能过多,否则内存溢出 C:构造方法不能递归使用     三.举例子  递归 ...

  4. java基础06 switch

    public class SwitchDemo01 { /** * 韩嫣参加计算机编程大赛 如果获得第一名,将参加麻省理工大学组织的1个月夏令营 如果获得第二名,将奖励惠普笔记本电脑一部 如果获得第三 ...

  5. 074 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 06 综合案例-数组移位-主方法功能3的实现

    074 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 06 综合案例-数组移位-主方法功能3的实现 本文知识点:综合案例-数组移位-主方法功能3的实现 说明:因为 ...

  6. 068 01 Android 零基础入门 01 Java基础语法 08 Java方法 06 参数传递问题——基本数据类型传值

    068 01 Android 零基础入门 01 Java基础语法 08 Java方法 06 参数传递问题--基本数据类型传值 本文知识点:参数传递问题--基本数据类型传值 说明:因为时间紧张,本人写博 ...

  7. 061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结

    061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结 本文知识点:一维数组总结 总结 注意点

  8. 060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序

    060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序 本文知识点:冒泡排序 冒泡排序 实际案例分析冒泡排序流程 第1轮比较: 第1轮比较的结果:把最 ...

  9. 059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环

    059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环 本文知识点:增强型for循环 增强型for循环格式 案例练习增强型for循环 数组名字 ...

随机推荐

  1. Mysql 外键设置

    MySql外键设置详解 (1) 外键的使用: 外键的作用,主要有两个:    一个是让数据库自己通过外键来保证数据的完整性和一致性    一个就是能够增加ER图的可读性    有些人认为外键的建立会给 ...

  2. QString::toLocal8Bit得听QTextCodec::codecForLocale的

    这个函数用了这么久,到今天程序出错才发现这个问题...也就是说,必须设置QTextCodec *codec = QTextCodec::codecForName("System") ...

  3. Xamarin.Android开发实践(一)

    原文:Xamarin.Android开发实践(一) 一.准备工作 1.创建一个空的解决方案,并命名为Phoneword 2.右击解决方案 新建->新建项目 并命名为Phoneword_Droid ...

  4. Windows XP硬盘安装Ubuntu 12.04双系统图文详解

    Windows XP硬盘安装Ubuntu 12.04双系统图文详解 Ubuntu 12.04 LTS版本于2012年4月26日发布,趁着五一放假,赶紧在自己的Windows XP的电脑上安装下Ubun ...

  5. VS2010/MFC对话框四:为控件添加消息处理函数

    为控件添加消息处理函数 创建对话框类和添加控件变量在上一讲中已经讲过,这一讲的主要内容是如何为控件添加消息处理函数. MFC为对话框和控件等定义了诸多消息,我们对它们操作时会触发消息,这些消息最终由消 ...

  6. Cin、Cout 加快效率方法

    std::ios::sync_with_stdio(false); 在main 函数中加上这么一句话. 可以打消iostream的输入输出缓存,可以节省许多时间,使效率与scanf与printf相差无 ...

  7. Spirng+SpringMVC+Maven+Mybatis+MySQL项目搭建(转)

    这篇文章主要讲解使用eclipse对Spirng+SpringMVC+Maven+Mybatis+MySQL项目搭建过程,包括里面步骤和里面的配置文件如何配置等等都会详细说明. 如果还没有搭建好环境( ...

  8. hdu 4885 TIANKENG’s travel(bfs)

    题目链接:hdu 4885 TIANKENG's travel 题目大意:给定N,L,表示有N个加油站,每次加满油能够移动距离L,必须走直线,可是能够为斜线.然后给出sx,sy,ex,ey,以及N个加 ...

  9. 另一种数据库连接字符串的编写方式(Sqlbuilder)

    SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); builder.DataSource = "&q ...

  10. (Relax njuptoj)1009 数的计算(DP)

    其实DP 的关键在于找到子问题的结构.  我们规定arr[i][j]为在j左边填写i时的数的个数,很明显:  arr[i][j]=a[0][i]+a[1][i]+...+arr[i/2][i](i&l ...