⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tij0128.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 3 页
字号:
    fq = q;
    seeds = seedCount;
    s = <font color="#0000ff">new</font> Seed[seeds];
    <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i &lt; seeds; i++)
      s[i] = <font color="#0000ff">new</font> Seed();
  }
  <font color="#009900">// Other constructors:</font>
  <font color="#009900">// ...</font>
  <font color="#009900">// Copy constructor:</font>
  Fruit(Fruit f) {
    fq = <font color="#0000ff">new</font> FruitQualities(f.fq);
    seeds = f.seeds;
    <font color="#009900">// Call all Seed copy-constructors:</font>
    <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i &lt; seeds; i++)
      s[i] = <font color="#0000ff">new</font> Seed(f.s[i]);
    <font color="#009900">// Other copy-construction activities...</font>
  }
  <font color="#009900">// To allow derived constructors (or other </font>
  <font color="#009900">// methods) to put in different qualities:</font>
  <font color="#0000ff">protected</font> <font color="#0000ff">void</font> addQualities(FruitQualities q) {
    fq = q;
  }
  <font color="#0000ff">protected</font> FruitQualities getQualities() {
    <font color="#0000ff">return</font> fq;
  }
}

<font color="#0000ff">class</font> Tomato <font color="#0000ff">extends</font> Fruit {
  Tomato() {
    <font color="#0000ff">super</font>(<font color="#0000ff">new</font> FruitQualities(), 100);
  }
  Tomato(Tomato t) { <font color="#009900">// Copy-constructor</font>
    <font color="#0000ff">super</font>(t); <font color="#009900">// Upcast for base copy-constructor</font>
    <font color="#009900">// Other copy-construction activities...</font>
  }
}

<font color="#0000ff">class</font> ZebraQualities <font color="#0000ff">extends</font> FruitQualities {
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> stripedness;
  ZebraQualities() { <font color="#009900">// Default constructor</font>
    <font color="#009900">// do something meaningful...</font>
  }
  ZebraQualities(ZebraQualities z) {
    <font color="#0000ff">super</font>(z);
    stripedness = z.stripedness;
  }
}

<font color="#0000ff">class</font> GreenZebra <font color="#0000ff">extends</font> Tomato {
  GreenZebra() {
    addQualities(<font color="#0000ff">new</font> ZebraQualities());
  }
  GreenZebra(GreenZebra g) {
    <font color="#0000ff">super</font>(g); <font color="#009900">// Calls Tomato(Tomato)</font>
    <font color="#009900">// Restore the right qualities:</font>
    addQualities(<font color="#0000ff">new</font> ZebraQualities());
  }
  <font color="#0000ff">void</font> evaluate() {
    ZebraQualities zq = 
      (ZebraQualities)getQualities();
    <font color="#009900">// Do something with the qualities</font>
    <font color="#009900">// ...</font>
  }
}

<font color="#0000ff">public</font> <font color="#0000ff">class</font> CopyConstructor {
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> ripen(Tomato t) {
    <font color="#009900">// Use the "copy constructor":</font>
    t = <font color="#0000ff">new</font> Tomato(t); 
    System.out.println("In ripen, t is a " +
      t.getClass().getName());
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> slice(Fruit f) {
    f = <font color="#0000ff">new</font> Fruit(f); <font color="#009900">// Hmmm... will this work?</font>
    System.out.println("In slice, f is a " +
      f.getClass().getName());
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    Tomato tomato = <font color="#0000ff">new</font> Tomato();
    ripen(tomato); <font color="#009900">// OK</font>
    slice(tomato); <font color="#009900">// OOPS!</font>
    GreenZebra g = <font color="#0000ff">new</font> GreenZebra();
    ripen(g); <font color="#009900">// OOPS!</font>
    slice(g); <font color="#009900">// OOPS!</font>
    g.evaluate();
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
seems a bit strange at first. Sure, fruit has qualities, but why not just put
data members representing those qualities directly into the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class? There are two potential reasons. The first is that you might want to
easily insert or change the qualities. Note that 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
has a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addQualities(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method to allow derived classes to do this. (You might think the logical thing
to do is to have a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
constructor in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that takes a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>FruitQualities</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
argument, but constructors don&#8217;t inherit so it wouldn&#8217;t be
available in second or greater level classes.) By making the fruit qualities
into a separate class, you have greater flexibility, including the ability to
change the qualities midway through the lifetime of a particular 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
second reason for making 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>FruitQualities</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
a separate object is in case you want to add new qualities or to change the
behavior via inheritance and polymorphism. Note that for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>GreenZebra</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(which really is a type of tomato &#8211; I&#8217;ve grown them and
they&#8217;re fabulous), the constructor calls 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addQualities(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and passes it a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ZebraQualities</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object, which is derived from 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>FruitQualities</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
so it can be attached to the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>FruitQualities</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
handle in the base class. Of course, when 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>GreenZebra</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
uses the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>FruitQualities</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
it must downcast it to the correct type (as seen in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>evaluate(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">),
but it always knows that type is 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ZebraQualities</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You&#8217;ll
also see that there&#8217;s a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Seed</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class, and that 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(which by definition carries its own seeds) contains an array of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Seed</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Finally,
notice that each class has a copy constructor, and that each copy constructor
must take care to call the copy constructors for the base class and member
objects to produce a deep copy. The copy constructor is tested inside the class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CopyConstructor</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The method 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ripen(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
takes a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Tomato
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">argument
and performs copy-construction on it in order to duplicate the object:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">t
= new Tomato(t);
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">while
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>slice(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
takes a more generic 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object and also duplicates it:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">f
= new Fruit(f);
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">These
are tested with different kinds of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Here&#8217;s the output:
</FONT><P></DIV>

<font color="#990000"><PRE>In ripen, t is a Tomato
In slice, f is a Fruit
In ripen, t is a Tomato
In slice, f is a Fruit </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
is where the problem shows up. After the copy-construction that happens to the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Tomato</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
inside 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>slice(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the result is no longer a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Tomato</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object, but just a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
It has lost all of its tomato-ness. Further, when you take a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>GreenZebra</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
both 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ripen(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>slice(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
turn it into a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Tomato</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Fruit</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
respectively. Thus, unfortunately, the copy constructor scheme is no good to us
in Java when attempting to make a local copy of an object.
</FONT><P></DIV>
<A NAME="Heading382"></A><H4 ALIGN=LEFT>
Why
does it work in C++ and not Java?
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
copy constructor is a fundamental part of C++, since it automatically makes a
local copy of an object. Yet the example above proves that it does not work for
Java. Why? In Java everything that we manipulate is a handle, while in C++ you
can have handle-like entities and you can 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>also</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
pass around the objects directly. That&#8217;s what the C++ copy constructor is
for: when you want to take an object and pass it in by value, thus duplicating
the object. So it works fine in C++, but you should keep in mind that this
scheme fails in Java, so don&#8217;t use it.
</FONT><a name="_Toc375545433"></a><a name="_Toc408018669"></a><P></DIV>

<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0127.html">Prev</a> | <a href="tij0129.html">Next</a>
</div>
</body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -