`
seawavenews
  • 浏览: 230185 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

Java咖啡馆(8)——大话面向对象(下)

阅读更多

 构思这篇咖啡馆的时候时值奥运圣火熊熊燃烧,看到中国奥运代表团努力为国争光,不由不决定把这次的主题献给我们的奥运健儿!

面向对象编程

  如果你是Java咖啡馆的常客,那么在不知不觉中你早已接触并运用过Java的面向对象知识。在这回的咖啡馆中,让我们详细剖析一个面向对象编程的实例,把知识巩固下来。

  奥运是国际性的运动盛会,中国运动员自然要用英文形式的名字才便于同国际接轨。这回要编写的程序便是用来解析英文名字的工具。通常,Gary Chan这样的英文名字形式表示名在前、姓在后。而Yao, Ming这样的形式则表示姓在前名在后。大家千万不要以为Gary在这里平白无故用Yao, Ming打广告,Yao初中时候可是跟Gary一个班的,他被语文老师仰着头臭骂痛哭后,经常是Gary安慰他,并经常一同骑车回家。看着今日的Yao已经是世界级的运动员为国争光了,Gary更需要加倍努力了……

  OK,言归正传,我们的程序将自动判断名字形式,并且分解出姓和名。还是老规矩,请用Eclipse生成一个名为Chap 07 NameParser的项目,并且加入一个新的名为NameParser类,在Package属性填写com.cfan.garychan.nameparser。如果你忘记了package的知识,请参考《Java咖啡馆(6)—编写猜数字游戏 》中关于包概念的描述。

  回顾一下,类是定义了从类生成的实例(instance)中的数据和方法的关系的模板。有人喜欢把类比作图章,图章敲出来的图案便是对象,的确很形象。

  Java中用class关键字来定义类,不过我们用Eclipse来定义更加方便。仍然用Eclipse新建一个叫做Namer的类,记得不要在public static void main(String[] args)前面打勾,确定后Eclipse便生成一个新的Java源文件Namer.java,里面的代码如下:

public class Namer {

}

  这个类非常简单,可惜不能做任何事情。

  1.封装

  面向对象程序设计中,一个非常重要的技术便是封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。这样做的好处在于可以使类内部的具体实现透明化,只要其他代码不依赖类内部的私房数据,你便可以安心修改这些代码。此外,这样做也是出于安全方面的考虑,如果代表网上支付卡密码的变量随便就可以被访问到,这样的系统谁还敢用呢?

  封装主要依靠对类、数据和方法的访问控制,从语法上讲就是加上private、protected、public等关键词,如果没有关键词修饰则默认为package。它们控制权限如下表所示:

Specifier 类 子类 包 世界
private X
protected X X* X
public X X X X
package X X

  注意上面的X*,父类的protected部分,只有在与父类在同一个包内的子类才能够访问,否则也是不可访问的。

  让我们结合实例理解一下。稍微把Namer类改一下:

public class Namer {
    protected String surname;  // 姓
    protected String firstname; // 名

    public String getFirstname() {
        return firstname;
    }

    public String getSurname() {
        return surname;
    }
}

  这个类有两个String类型的成员变量,surname和firstname,分别用来储存姓和名。这两个成员变量前都有protected修饰词,按照表格,这两个变量仅能够被类本身、子类以及包中其他类操作,而包外的类则无权访问。不过,为了跟包外的代码进行沟通,Namer类提供了getFirstname和getSurname这两个public的方法。从而,对包外的类而言,姓名数据是只读的。

 2.继承

  对象是用类来定义的。通过类,你能够充分了解对象的全貌。比如,一说起自行车,你就会联想到自行车是有两个轮子、车把以及脚踏板。

  更进一步,面向对象语言的另一个特点便是允许从一个已有的类定义新的类。比如,山地车、公路赛车和两人三轮车都是自行车。在面向对象语言中,你可以从一个已经有的自行车类定义山地车类、公路赛车类等等。山地车类、公路赛车类都称为自行车类的子类,自行车类是它们的父类,而这种定义关系,便是继承关系。

  子类继承了父类的属性。比如,山地车、公路赛车都是有两个轮子一个车座。子类也可继承了父类的方法,比如山地车、公路赛车、两人三轮车都可以前进、刹车、转弯等。
当然,子类并不限于继承,还可以发扬光大。比如两人三轮车便颠覆了自行车只有两个轮子、一个座垫的属性,使得自己更加休闲潇洒。

  让我们看看如何运用继承来处理名在姓之前的模式。这种模式中,由于姓和名是用空格分割的,所以程序如下:

class FirstFirst extends Namer {
    public FirstFirst(String s) {
        int i = s.lastIndexOf(" "); // 搜索空格
        if (i > 0) {
            firstname = s.substring(0, i).trim();
            surname = s.substring(i + 1).trim();
        }
    }
}

  FirstFirst类通过extends关键词表示对Namer类进行继承,只有一个类方法,名字恰好是FirstFirst。这并不是一个巧合。

  所有的Java类都拥有若干特殊方法用来初始化对象,它们称为构造函数,特征就是与类同名,可以带有或者没有参数。这种同名函数不同参数的现象,在面向对象中称作重载(Overload)。拿以前使用new操作符生成随机数的代码来说:

Random random = new Random();

  new操作符实例化一个Random对象后,紧接着就调用了Random类的构造函数进行初始化,只不过这个构造函数没有参数。没有参数的构造函数,称为默认构造函数。默认的构造函数是每个类都拥有的,即使没有声明在代码中,Java编译器在编译时也会自动加入。

  回过头来看FirstFirst类。FirstFirst类继承自Namer类,从而也拥有自己的firstname和surname属性。在FirstFirst类的构造函数中,通过解析参数s,通过搜索空格的方法来解析出空格前面的名和空格后面的姓,从而执行

FirstFirst parser = new FirstFirst("Gary Chan");

  之后,我的姓和名已经解析出来并且分别保存在firstname和surname变量中了。同时,FirstFirst类继承了Namer的方法,从而便可以通过如下语句来返回姓——Gary了:

String mySername = parser.getSurname();

  注意,我们并没有在FirstFirst类中定义getSurname()方法,这是从父类继承来的,这就是代码重用的概念,避免了无谓的重复劳动。

  有了上面的基础,再来编写名在姓之后的模式:

class FirstLast extends Namer {
    public FirstLast(String s) {
        int i = s.indexOf(","); // 搜索逗号
        if (i > 0) {
            surname = s.substring(0, i).trim();
            firstname = s.substring(i + 1).trim();
        }
    }
}

  由此可见,Namer类的两个子类拥有它全部的属性和方法,并且在其之上更加入了解析姓名的能力,而代码却增加不多。代码重用,这是面向对象的主要魅力之一!

 3.多态

  至此,我们已经分别为两种名字解析方法编写了两个类,即FirstLast类和FirstFirst类。为了更好地使用这两个类,让我们玩一些小技巧。

  首先,对于姓名解析器的使用者,具体是使用Namer类还是FirstLast类还是FirstFirst类,他是不关心的。这些东西最好都是自动化的,他只要能得到姓和名即可。
其次,如果你是属于胆大心细遇事不慌的(阿庆嫂类型)IT青年的话,一定会发现Namer.java中只有Namer类是public的,FirstFirst类和FirstLast类之前没有修饰——它们是默认的package的,也就是说,在com.cfan.garychan.nameparser包之外,都是无法被访问到的。

  如果仅仅能够Namer类来解析姓名那该多好啊!

  实际上,运用多态的概念,这些问题将迎刃而解。

  面向对象一共有三个特性:封装、继承、多态。所谓封装,就是通过定义类并且给类的属性和方法加上访问控制来抽象事物的本质特性。所谓继承,就是代码重用。而多态,从另外一个角度分割了接口和实现,即把“什么”和“如何”两个概念分离开来。举个例子,公路赛车是自行车,继承了自行车的刹车方法。假设你和朋友骑着捷安特的公路赛车出游,当你的朋友正好侧着脸看风景时,前面突然窜出来一只猫,你一定大声惊呼:赶快刹车!仔细体会这句话,你的意识中只是知道自行车可以刹车,所以让朋友按下车闸让自行车刹车,而绝对不是认为—捷安特牌子的公路赛车赶快刹车!从而,思考的是抽象的
自行车的刹车,而最终动作却是捷安特牌子的公路赛车刹车,通过类指代实例,这就是多态的概念。

  回过头看我们的程序,public的Namer类正好是FirstFirst类和FirstLast类的共同父类,应用多态的概念实在是太合适不过了。新建一个名为NameFactory的类,并且把这个类也放在com.cfan.garychan.nameparser包中,代码如下:

public class NameFactory {
    public static Namer getNamer(String entry) {
    if (entry.indexOf(",") > 0)
        return new FirstLast(entry); //return one class
    else if (entry.indexOf(" ") > 0)
        return new FirstFirst(entry); //or the other
    else
        return null;
    }
}

  NameFactory类只有一个静态方法getNamer,注意返回的是一个Namer类。下面根据entry参数是否包含“,”符号来确定实际生成的是FirstLast类还是FirstFirst类,最终将其返回。你看,说是返回Namer类,实际返回的是FirstLast类或者FirstFirst类,这就是多态的典型应用。需要注意的是,并非毫不相关的类都能够当作多态使用,必须是有继承关系,而且有方向性。结合生活经验,多态的概念并不难理解。

  最后让我们看看如何使用这个姓名解析器。新建Chap07NameParser类,Package是com.cfan.garychan,代码如下:

package com.cfan.garychan;

import com.cfan.garychan.nameparser.NameFactory;
import com.cfan.garychan.nameparser.Namer;

/**
* 用解析器解析姚明的英文名字。
*/
public class Chap07NameParser {
    public static void main(String[] args) {
        Namer namer = NameFactory.getNamer("Yao, Ming");
        if (null == namer) {
            System.out.println("姓名不合法");
        else {
            System.out.println("姓:" + namer.getSurname());
            System.out.println("名:" + namer.getFirstname());
        }
    }
}

  你看,我们通过NameFactory返回一个Namer对象,这个对象能够解析姚明的英文名字,你不必关心这个Namer对象究竟是FirstFirst类还是FirstLast类,方便极了。

面向对象的未来

  面向对象技术是软件技术自然演变的结果,在许多领域有着强大的生命力与美好的前景。借用Maurice Wilkes在他的图灵奖领奖仪式上的话,“面向对象技术是70年代以来最激动人心的革新之一”。然而,面向对象并非包治百病的灵丹妙药,其发展还远未成熟,还有许多问题值得我们付出真正的热情!

 
分享到:
评论

相关推荐

    java版大话西游源码

    《Java版大话西游源码》是一款基于Java编程语言开发的角色扮演游戏(RPG)教程,对于初学者和想要深入理解游戏开发的程序员来说,它提供了丰富的学习资源。这款教程涵盖了多线程技术和自动寻路算法等核心概念,是...

    (JAVA)大话类、方法、参数、对象、属性以及面向对象的开发模式.pdf

    (JAVA)大话类、方法、参数、对象、属性以及面向对象的开发模式.pdf

    Java咖啡馆电子书

    用通俗易懂的语言介绍了java,主要内容包括:叹咖啡、第一杯咖啡、Eclipse、品味第一杯咖啡、Java语言基础、编写猜数字游戏、大话面向对象、一个压缩归档实用软件、情人节的Applet、Java插件技术、Tic-Tac-Toe、终结...

    JAVA咖啡馆

    叹咖啡 第一杯咖啡 EcliPse 品味第一杯咖啡 Java语言基础 编写猜数字游戏 大话面向对象 个压缩归档实用软件 情人节的Applet Java插件技术 Tic-Tac-Toe 终结者

    大话JAVA:从零基础到数据库、WEB开发.

    大话Java:从零基础到数据库、Web开发以漫画的形式,由浅入深、循序渐进地介绍Java编程的常用技术和方法,内容涵盖了Java基本语法结构、面向对象特征、集合框架体系、异常处理、GUI编程、MySQL数据库、JDBC数据库...

    【资源免费下载】Java代码积累丨大话设计模式(Java实现版本)、线程协作

    Java代码加速器 Java代码积累:并发 设计模式 数据结构 使用容器 实用 类 基础知识 并发性 演示线程的生命周期 生产者-消费者 设计模式参考《大话设计模式》 工厂简单模式 创造型模式 工厂方法模式 抽象工厂模式 ...

    大话Java性能优化

    3.1 面向对象及基础类型 3.2 集合类概念 3.3 字符串概念 3.4 引用类型概念 3.5 其他相关概念 3.6 本章小结 第4章 程序设计优化建议 4.1 算法优化概述 4.2 设计模式 4.3 I/O及网络相关优化 4.4 数据应用...

    (JAVA)大话类、方法、参数、对象、属性以及面向对象的开发模式[归类].pdf

    在Java编程中,类(Class)是面向对象编程的基础,它代表了一组具有相同特征和行为的实例的模板。类可以看作是对现实世界中某一类事物的抽象,例如,人、动物或者汽车。类定义了对象的属性(Attributes)和方法...

    大话存储终极版——扫描件

    《大话存储终极版》是IT领域内一本深受读者喜爱的存储技术图书,作者冬瓜哥(张冬)以其通俗易懂的语言,深入浅出地介绍了存储领域的诸多知识。这本书对于初学者来说是一份非常宝贵的资源,可以帮助他们快速入门并...

    大话java性能优化 周明耀 完整版

    《大话java性能优化》是周明耀先生的一本深入探讨Java性能调优的专业书籍,其主要内容涵盖了Java程序设计中的各种性能优化策略和技术。这本书旨在帮助开发者理解和掌握如何提升Java应用的运行效率,减少资源消耗,...

    大话JAVA性能优化.pdf

    大话Java性能优化》主要提供Java性能调优方面的参考建议及经验交流。作者力求做到知识的综合传播,而不是仅仅只针对Java虚拟机调优进行讲解,另外力求每一章节都有实际的案例支撑。具体包括:性能优化策略、程序编写...

    大话JAVA:从零基础到数据库、WEB开发

    Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向...

    大话JAVA性能优化

    《大话JAVA性能优化》这份文档深入探讨了Java程序在多个层面的性能调优策略,旨在帮助开发者提高程序运行效率,降低资源消耗,提升用户体验。以下是对这些知识点的详细阐述: 1. **代码层次优化**:在代码编写阶段...

    大话java性能优化

    大话java性能优化,大家可以搜一下这本书。这个是完美中文版,建议下载

    大话设计模式完整版,面向对象程序设计

    大话设计模式完整版,伍迷戏说面向对象程序设计

    Android之大话设计模式——:抽象工厂模式借鉴.pdf

    Android之大话设计模式——:抽象工厂模式借鉴.pdf

    Wechat_Dice:微信小程序——大话色

    微信小程序——大话骰 核心是调用wx.onAccelerometerChange()API,监测手机上下摇动重力变化,来实现摇一摇功能。 玩法: 点击按钮 -> 骰子转动 -> 按钮提示变化(请摇一摇手机) -> 摇动成功时手机释放震动,骰子...

Global site tag (gtag.js) - Google Analytics