当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:17:00  来源:本站整理

副本构建器[Java编程]

赞助商链接



  本文“副本构建器[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
克隆看起来要求举行非常复杂的设置,仿佛还该有另一种替换筹划.一个办法是制作特别的构建器,令其负责复制一个对象.在C++中,这叫作“副本构建器”.刚开始的时刻,这好象是一种非常明显的办理筹划(假如你是C++程序员,这个办法就更显密切).下面是一个实际的例子:
//: CopyConstructor.java
// A constructor for copying an object
// of the same type, as an attempt to create
// a local copy.

class FruitQualities {
  private int weight;
  private int color;
  private int firmness;
  private int ripeness;
  private int smell;
  // etc.
  FruitQualities() { // Default constructor
    // do something meaningful...
  }
  // Other constructors:
  // ...
  // Copy constructor:
  FruitQualities(FruitQualities f) {
    weight = f.weight;
    color = f.color;
    firmness = f.firmness;
    ripeness = f.ripeness;
    smell = f.smell;
    // etc.
  }
}

class Seed {
  // Members...
  Seed() { /* Default constructor */ }
  Seed(Seed s) { /* Copy constructor */ }
}

class Fruit {
  private FruitQualities fq;
  private int seeds;
  private Seed[] s;
  Fruit(FruitQualities q, int seedCount) { 
    fq = q;
    seeds = seedCount;
    s = new Seed[seeds];
    for(int i = 0; i < seeds; i++)
      s[i] = new Seed();
  }
  // Other constructors:
  // ...
  // Copy constructor:
  Fruit(Fruit f) {
    fq = new FruitQualities(f.fq);
    seeds = f.seeds;
    // Call all Seed copy-constructors:
    for(int i = 0; i < seeds; i++)
      s[i] = new Seed(f.s[i]);
    // Other copy-construction activities...
  }
  // To allow derived constructors (or other 
  // methods) to put in different qualities:
  protected void addQualities(FruitQualities q) {
    fq = q;
  }
  protected FruitQualities getQualities() {
    return fq;
  }
}

class Tomato extends Fruit {
  Tomato() {
    super(new FruitQualities(), 100);
  }
  Tomato(Tomato t) { // Copy-constructor
    super(t); // Upcast for base copy-constructor
    // Other copy-construction activities...
  }
}

class ZebraQualities extends FruitQualities {
  private int stripedness;
  ZebraQualities() { // Default constructor
    // do something meaningful...
  }
  ZebraQualities(ZebraQualities z) {
    super(z);
    stripedness = z.stripedness;
  }
}

class GreenZebra extends Tomato {
  GreenZebra() {
    addQualities(new ZebraQualities());
  }
  GreenZebra(GreenZebra g) {
    super(g); // Calls Tomato(Tomato)
    // Restore the right qualities:
    addQualities(new ZebraQualities());
  }
  void evaluate() {
    ZebraQualities zq = 
      (ZebraQualities)getQualities();
    // Do something with the qualities
    // ...
  }
}

public class CopyConstructor {
  public static void ripen(Tomato t) {
    // Use the "copy constructor":
    t = new Tomato(t); 
    System.out.println("In ripen, t is a " +
      t.getClass().getName());
  }
  public static void slice(Fruit f) {
    f = new Fruit(f); // Hmmm... will this work?
    System.out.println("In slice, f is a " +
      f.getClass().getName());
  }
  public static void main(String[] args) {
    Tomato tomato = new Tomato();
    ripen(tomato); // OK
    slice(tomato); // OOPS!
    GreenZebra g = new GreenZebra();
    ripen(g); // OOPS!
    slice(g); // OOPS!
    g.evaluate();
  }
} ///:~
这个例子第一眼看上去显得有点奇特.差别生果的质量必定有所辨别,但为什么只是把代表那些质量的数据成员直接置入Fruit(生果)类?有两方面大概的缘由.第一个是我们大概想简便地插入或改正质量.注意Fruit有一个protected(遭到保护的)addQualities()办法,它答应衍生类来举行这些插入或改正操作(大家大概会认为最合乎逻辑的做法是在Fruit中利用一个protected构建器,用它获得FruitQualities参数,但构建器不能担当,所以不可在第二级或级数更深的类中利用它).通过将生果的质量置入一个独立的类,可以得到更大的机动性,此中包含可以在特定Fruit对象的存在期间半途更改质量.
之所以将FruitQualities设为一个独立的对象,另一个缘由是考虑到我们有时但愿增添新的质量,大概通过担当与多形性改变行为.注意对GreenZebra来说(这实际是西红柿的一类——我已栽种成功,它们简直令人难以置信),构建器会调用addQualities(),并为其传送一个ZebraQualities对象.该对象是从FruitQualities衍生出来的,所以能与底子类中的FruitQualities句柄接洽在一同.当然,一旦GreenZebra利用FruitQualities,就必须将其下溯造型成为精确的范例(就象evaluate()中展示的那样),但它必定知道范例是ZebraQualities.
大家也看到有一个Seed(种子)类,Fruit(大家都知道,生果含有自己的种子)包含了一个Seed数组.
最后,注意每个类都有一个副本构建器,并且每个副本构建器都必须关心为底子类和成员对象调用副本构建器的问题,从而得到“深层复制”的效果.对副本构建器的测试是在CopyConstructor类内举行的.办法ripen()需求获得一个Tomato参数,并对其履行副本构建工作,以便复制对象:
t = new Tomato(t);
而slice()需求获得一个更通例的Fruit对象,并且对它举行复制:
f = new Fruit(f);
它们都在main()中伴随差别种类的Fruit举行测试.下面是输出后果:
In ripen, t is a Tomato
In slice, f is a Fruit
In ripen, t is a Tomato
In slice, f is a Fruit
从中可以看出一个问题.在slice()内部对Tomato举行了副本构建工作今后,后果便不再是一个Tomato对象,而只是一个Fruit.它已丧失了作为一个Tomato(西红柿)的全部特点.此外,假如采取一个GreenZebra,ripen()和slice()会把它辨别转换成一个Tomato和一个Fruit.所以非常不幸,假定想制作对象的一个本地副本,Java中的副本构建器便不是分外合适我们.

1. 为什么在C++的作用比在Java中大?
副本构建器是C++的一个基本构成部份,因为它能自动产生对象的一个本地副本.但前面的例子确切证明了它不合适在Java中利用,为什么呢?在Java中,我们操控的一切东西都是句柄,而在C++中,却可以利用近似于句柄的东西,也能直接传送对象.这时便要用到C++的副本构建器:只要想得到一个对象,并按值传送它,便可以复制对象.所以它在C++里能很好地工作,但应注意这套机制在Java里是很不通的,所以不要用它.
  以上是“副本构建器[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • 副本构建器
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .