类再生

Thinking in Java 第六章 类再生

有两个实现类再生的方法:

第一个最简单:在新类里简单地创建原有类的对象。我们把这种方法叫作“合成”,因为新类由现有       类的对象合并而成。我们只是简单地重复利用代码的功能,而不是采用它的形式。

第二种方法则显得稍微有些技巧。它创建一个新类,将其作为现有类的一个“类型”。我们可以          原样采取现有类的形式,并在其中加入新代码,同时不会对现有的类产生影响。这种魔术般          的行为叫作“继承”(Inheritance),涉及的大多数工作都是由编译器完成的。

示例:

    第一种情况所涉及的内容

class Soap 
{
  private String s;
  Soap() 
  {
  System.out.println("Soap()");
  s = new String("Constructed");
   }
  public String toString() 
  {
   return s; 
   }
}
public class Bath 
{
  private String   // Initializing at point of definition:
  s1 = new String("Happy"),
  s2 = "Happy",
  s3, s4;
  Soap castille;
  int i;
  float toy;
  Bath() 
  {
    System.out.println("Inside Bath()");
    s3 = new String("Joy");
    i = 47;
    toy = 3.14f;
    castille = new Soap();
  }
  void print() 
  {  // Delayed initialization:
    if(s4 == null)
    s4 = new String("Joy");
    System.out.println("s1 = " + s1);
    System.out.println("s2 = " + s2);
    System.out.println("s3 = " + s3);
    System.out.println("s4 = " + s4);
    System.out.println("i = " + i);
    System.out.println("toy = " + toy);
    System.out.println("castille = " + castille);
  }
  public static void main(String[] args) 
  {
    Bath b = new Bath();
    b.print();
  }
}

请注意在Bath 构建器中,在所有初始化开始之前执行了一个语句。如果不在定义时进行初始化,仍然不能保证能在将一条消息发给一个对象句柄之前会执行任何初始化——除非出现不可避免的运行期违例。

下面是该程序的输出:

Inside Bath()

Soap()

s1 = Happy

s2 = Happy

s3 = Joy

s4 = Joy

i = 47

toy = 3.14

castille = Constructed

调用print()时,它会填充 s4,使所有字段在使用之前都获得正确的初始化。



第二种继承的方法:

用于合成的语法是非常简单且直观的。但为了进行继承,必须采用一种全然不同的形式。需要继承的   时候,我们会说:“这个新类和那个旧类差不多。”为了在代码里表面这一观念,需要给出类名。但   在类主体的开始花括号之前,需要放置一个关键字extends,在后面跟随“基础类”的名字。若采取这   种做法,就可自动获得基础类的所有数据成员以及方法。

示例:

class Cleanser 
{
  private String s = new String("Cleanser");
  public void append(String a) { s += a; }
  public void dilute() { append(" dilute()"); }
  public void apply() { append(" apply()"); }
  public void scrub() { append(" scrub()"); }
  public void print() { System.out.println(s); }
  public static void main(String[] args) 
  {
    Cleanser x = new Cleanser();
    x.dilute(); x.apply(); x.scrub();
    x.print();
   }
}
public class Detergent extends Cleanser 
{
   // Change a method:
  public void scrub() 
  {
    append(" Detergent.scrub()");
    super.scrub(); // Call base-class version
  }
  // Add methods to the interface:
  public void foam() { append(" foam()"); }
  // Test the new class:
  public static void main(String[] args) 
  {
    Detergent x = new Detergent();
    x.dilute();
    x.apply();
    x.scrub();
    x.foam();
    x.print();
    System.out.println("Testing base class:");
    Cleanser.main(args);
  }
}

这个例子向大家展示了大量特性。首先,在Cleanser append()方法里,字串同一个s 连接起来。这是   用“+=”运算符实现的。同“+”一样,“+=”被Java 用于对字串进行“过载”处理。

进行继承时,我们并不限于只能使用基础类的方法。亦可在衍生出来的类里加入自己的新方法。这时   采取的做法与在普通类里添加其他任何方法是完全一样的:只需简单地定义它即可。extends关键字提   醒我们准备将新方法加入基础类的接口里,对其进行“扩展”。foam()便是这种做法的一个产物。

 

  基础类的初始化:

    基础类子对象应该正确地初始化,而且只有一种方法能保证这一点:在构建器中执行初始化,通         过调用基础类构建器,后者有足够的能力和权限来执行对基础类的初始化。在衍生类的构建器中,      Java 会自动插入对基础类构建器的调用。

下面这个例子向大家展示了对这种三级继承的应用:

class Art 
{
  Art() {
  System.out.println("Art constructor");
  }
}
class Drawing extends Art 
{
  Drawing() {
  System.out.println("Drawing constructor");
  }
}
public class Cartoon extends Drawing 
{
  Cartoon() {
  System.out.println("Cartoon constructor");
  }
  public static void main(String[] args) {
  Cartoon x = new Cartoon();
  }
}

该程序的输出显示了自动调用:

Art constructor

Drawing constructor

Cartoon constructor

如果构造器内含有变量应该调用super来完成对基础类的调用,

如下例子:

class Game 
{
  Game(int i) {
  System.out.println("Game constructor");
  }
}
class BoardGame extends Game 
{
  BoardGame(int i) {
  super(i);
  System.out.println("BoardGame constructor");
  }
}
public class Chess extends BoardGame {
  Chess() {
  super(11);
  System.out.println("Chess constructor");
  }
  public static void main(String[] args) {
  Chess x = new Chess();
  }
}

这同时也会防止衍生类构建器捕获来自一个基础类的任何违例事件。显然,这有时会为我们造成不便。

时间: 2024-10-24 19:26:55

类再生的相关文章

读TIJ -6 类再生

<Think in java·第 6 章类再生> 读TIJ -1 对象入门 中已经就代码复用性吐槽了.继承关系在结果上(不是为了代码复用而设计继承关系)为代码复用提供了新的途径. 本章看其目录就比较杂,程序员的内聚思想去哪儿了?合成复用优先--合成.继承,为什么实现继承是不好的-- 6.1 合成的语法 解释了一个例程,没有什么好说的.has_a关系. 6.2 继承的语法 [You can think of inheritance, then, as reusing the class.]Is_

8.JAVA编程思想类再生

欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/51040239 "Java 引人注目的一项特性是代码的重复使用或者再生.但最具革命意义的是,除代码的复制和修改以外,我们还能做多得多的其他事情." 在象C 那样的程序化语言里,代码的重复使用早已可行,但效果不是特别显著.与Java 的其他地方一样,这个方案解决的也是与类有关的问题.我们通过创建新类来重复使用代码,但却用不着重新创建,可以直接使用别人已建好并调试好的现成

设计模式之Adapter(适配器)(转)

定义: 将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份. 为何使用? 我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口. 怎么办? 使用Adapter,在这两种接口之间创建一个混合接口(混血儿). 如何使用? 实现Adapter方式,其实"think in Java"的"类再生"一节中已经提到,有两

设计模式大全

Longronglin之设计模式: Christopher Alexander 说过:“每个模式描写叙述了一个在我们周围不断反复发生的问题,以及该问题的解决方式的核心.这样,你就能一次重新地使用该方案而不必做反复劳动”. 模式描写叙述为:在一定环境中解决某一问题的方案,包含三个基本元素--问题,解决方式和环境. 阅读类图和对象图请先学习UML 创建模式 结构模式 行为模式 创建模式:对类的实例化过程的抽象.一些系统在创建对象时,须要动态地决定如何创建对象,创建哪些对象,以及如何组合和表示这些对象

设计模式大全(转)

设计模式大全 Longronglin之设计模式: Christopher Alexander 说过:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心.这样,你就能一次又一次地使用该方案而不必做重复劳动”. 模式描述为:在一定环境中解决某一问题的方案,包括三个基本元素--问题,解决方案和环境. 阅读类图和对象图请先学习UML 创建模式 结构模式 行为模式 创建模式:对类的实例化过程的抽象.一些系统在创建对象时,需要动态地决定怎样创建对象,创建哪些对象,以及如何组合和表

Java适配器模式(Adapter模式)

适配器模式定义:将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份. 为何使用适配器模式 我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口. 怎么办? 使用Adapter,在这两种接口之间创建一个混合接口(混血儿). 如何使用适配器模式 实现Adapter方式,其实"think in Java"的"类再生&quo

设计模式学习之Adaptor

设计模式之Adapter(适配器) 适配器模式定义:    将两个不兼容的类纠合在一起使用,属于结构型模式,需要有 Adaptee(被适配者)和Adaptor(适配器)两个身份.为何使用?    我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口. 怎么办?使用 Adapter,在这两种接口之间创建一个混合接口(混血儿).如何使用?实现 Adapter 方式,其实"think in Java&qu

Java设计模式(学习整理)---迭代模式

设计模式之Adapter(适配器) 1.定义: 将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份. 2.为何使用? 我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口. 怎么办? 使用Adapter,在这两种接口之间创建一个混合接口(混血儿). 3.如何使用? 实现Adapter方式,其实"think in Java"的&

侃侃Thinking In Java

我是从Bruce Eckel的网站开始,读Thinking In Java 1st edition的,那是2000年左右.实话实说,对于TIJ,我又喜欢又讨厌它. 又喜欢又讨厌 正如大多数同学所感觉的,TIJ偏重于介绍面向对象的"思想",而不是像绝大多数(国内的)<Xxx程序设计>之类的书籍,前者是思想流派,后者是语法流.这点很吸引我,而且,这也是我写<编程导论(Java)>时学习的地方. 但,我并没有完整地读完TIJ,因为 我不喜欢他的讲述方式.Bruce E