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

📄 chapter07.html

📁 java 是一个很好的网络开发环境。由于它是通过解释的方法
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:Tjava14.rtf
Application Directory:c:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:02/04/2000
Translation Time:23:24:54
Translation Platform:Win32
Number of Output files:27
This File:Chapter07.html
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>7: Polymorphism</TITLE>
</HEAD>

<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview-head.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana" size = "-1">
    [ <a href="README-HTML.txt">Viewing Hints</a> ]
    [ <a href="http://www.mindview.net/TIJ2/index.html">2nd Edition</a> ]
    [ <a href="http://www.mindview.net/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/Training.html">Seminars</a> ]
    [ <a href="http://www.mindview.net/javaCD2.html">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/CPPServices/#ConsultingServices">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana">
  Thinking in Java, 1st edition</FONT></H2>
  <H3><FONT FACE="Verdana">&copy;1998 by Bruce Eckel</FONT></H3>
  
    <FONT FACE="Verdana" size = "-1">
     [ <a href="Chapter06.html">Previous Chapter</a> ] 
    [ <a href="SimpleContents.html">Short TOC</a> ] 
    [ <a href="Contents.html">Table of Contents</a> ] 
    [ <a href="DocIndex.html">Index</a> ]
     [ <a href="Chapter08.html">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="Chapter_7"></A><A NAME="_Toc375545326"></A><A NAME="_Toc407441451"></A><A NAME="_Toc408018529"></A><A NAME="Heading206"></A><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
7: Polymorphism<BR><A NAME="Index549"></A></H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>Polymorphism is the third
essential feature of an object-oriented programming language, after data
abstraction and inheritance. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It provides another dimension of
separation of interface from implementation, to decouple <I>what</I> from
<I>how</I>. Polymorphism allows improved code organization and readability as
well as the creation of <I>extensible</I> programs that can be
&#8220;grown&#8221; not only during the original creation of the project but
also when new features are desired.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Encapsulation creates new data
types by combining characteristics and behaviors. Implementation hiding
separates the interface from the implementation by making the details
<B>private</B>. This sort of mechanical organization makes ready sense to
someone with a procedural programming background. But polymorphism deals with
<A NAME="Index550"></A>decoupling in terms of <I>types</I>. In the last chapter,
you saw how <A NAME="Index551"></A>inheritance allows the treatment of an object
as its own type <I>or</I> its base type. This ability is critical because it
allows many types (derived from the same base type) to be treated as if they
were one type, and a single piece of code to work on all those different types
equally. The <A NAME="Index552"></A>polymorphic method call allows one type to
express its distinction from another, similar type, as long as they&#8217;re
both derived from the same base type. This distinction is expressed through
differences in behavior of the methods you can call through the base
class.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In this chapter, you&#8217;ll learn
about polymorphism (also called
<A NAME="Index553"></A><A NAME="Index554"></A><A NAME="Index555"></A><A NAME="Index556"></A><I>dynamic
binding</I> or <I>late binding</I> or <I>run-time binding</I>)<I> </I>starting
from the basics, with simple examples that strip away everything but the
polymorphic behavior of the
program.</FONT><A NAME="_Toc305593263"></A><A NAME="_Toc305628735"></A><A NAME="_Toc312374040"></A><A NAME="_Toc375545327"></A><A NAME="_Toc408018530"></A><BR></P></DIV>
<A NAME="Heading207"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Upcasting</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In Chapter 6 you saw how an object
can be used as its own type or as an object of its base type. Taking an object
handle and treating it as the handle of the base type is called
<I>upcasting<A NAME="Index557"></A></I> because of the way inheritance trees are
drawn with the base class at the top.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You also saw a problem arise, which
is embodied in the following: </FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: Music.java </font>
<font color=#009900>// Inheritance &amp; upcasting</font>
<font color=#0000ff>package</font> c07;

<font color=#0000ff>class</font> Note {
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> value;
  <font color=#0000ff>private</font> Note(<font color=#0000ff>int</font> val) { value = val; }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>final</font> Note
    middleC = <font color=#0000ff>new</font> Note(0), 
    cSharp = <font color=#0000ff>new</font> Note(1),
    cFlat = <font color=#0000ff>new</font> Note(2);
} <font color=#009900>// Etc.</font>

<font color=#0000ff>class</font> Instrument {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> play(Note n) {
    System.out.println(<font color=#004488>"Instrument.play()"</font>);
  }
}

<font color=#009900>// Wind objects are instruments</font>
<font color=#009900>// because they have the same interface:</font>
<font color=#0000ff>class</font> Wind <font color=#0000ff>extends</font> Instrument {
  <font color=#009900>// Redefine interface method:</font>
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> play(Note n) {
    System.out.println(<font color=#004488>"Wind.play()"</font>);
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Music {
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> tune(Instrument i) {
    <font color=#009900>// ...</font>
    i.play(Note.middleC);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Wind flute = <font color=#0000ff>new</font> Wind();
    tune(flute); <font color=#009900>// Upcasting</font>
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The method
<B>Music.tune(&#160;)</B> accepts an <B>Instrument </B>handle, but also anything
derived from <B>Instrument</B>. In <B>main(&#160;)</B>, you can see this
happening as a <B>Wind</B> handle is passed to <B>tune(&#160;)</B>, with no cast
necessary. This is acceptable; the interface in <B>Instrument</B> must exist in
<B>Wind</B>, because <B>Wind</B> is inherited from <B>Instrument</B>. Upcasting
from <B>Wind</B> to <B>Instrument</B> may &#8220;narrow&#8221; that interface,
but it cannot make it anything less than the full interface to
<B>Instrument</B>.</FONT><A NAME="_Toc375545328"></A><A NAME="_Toc408018531"></A><BR></P></DIV>
<A NAME="Heading208"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Why upcast?</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This program might seem strange to
you. Why should anyone intentionally <I>forget</I> the type of an object? This
is what happens when you upcast, and it seems like it could be much more
straightforward if <B>tune(&#160;)</B> simply takes a <B>Wind</B> handle as its
argument. This brings up an essential point: If you did that, you&#8217;d need
to write a new <B>tune(&#160;)</B> for every type of <B>Instrument</B> in your
system. Suppose we follow this reasoning and add <B>Stringed</B> and
<B>Brass</B> instruments:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: Music2.java </font>
<font color=#009900>// Overloading instead of upcasting</font>

<font color=#0000ff>class</font> Note2 {
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> value;
  <font color=#0000ff>private</font> Note2(<font color=#0000ff>int</font> val) { value = val; }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>final</font> Note2
    middleC = <font color=#0000ff>new</font> Note2(0), 
    cSharp = <font color=#0000ff>new</font> Note2(1),
    cFlat = <font color=#0000ff>new</font> Note2(2);
} <font color=#009900>// Etc.</font>

<font color=#0000ff>class</font> Instrument2 {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> play(Note2 n) {
    System.out.println(<font color=#004488>"Instrument2.play()"</font>);
  }
}

<font color=#0000ff>class</font> Wind2 <font color=#0000ff>extends</font> Instrument2 {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> play(Note2 n) {
    System.out.println(<font color=#004488>"Wind2.play()"</font>);
  }
}

<font color=#0000ff>class</font> Stringed2 <font color=#0000ff>extends</font> Instrument2 {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> play(Note2 n) {
    System.out.println(<font color=#004488>"Stringed2.play()"</font>);
  }
}

<font color=#0000ff>class</font> Brass2 <font color=#0000ff>extends</font> Instrument2 {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> play(Note2 n) {
    System.out.println(<font color=#004488>"Brass2.play()"</font>);
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Music2 {
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> tune(Wind2 i) {
    i.play(Note2.middleC);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> tune(Stringed2 i) {
    i.play(Note2.middleC);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> tune(Brass2 i) {
    i.play(Note2.middleC);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Wind2 flute = <font color=#0000ff>new</font> Wind2();
    Stringed2 violin = <font color=#0000ff>new</font> Stringed2();
    Brass2 frenchHorn = <font color=#0000ff>new</font> Brass2();
    tune(flute); <font color=#009900>// No upcasting</font>
    tune(violin);
    tune(frenchHorn);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This works, but there&#8217;s a
major drawback: You must write type-specific methods for each new
<B>Instrument2</B> class you add. This means more programming in the first
place, but it also means that if you want to add a new method like
<B>tune(&#160;)</B> or a new type of <B>Instrument</B>, you&#8217;ve got a lot
of work to do. Add the fact that the compiler won&#8217;t give you any error
messages if you forget to overload one of your methods and the whole process of
working with types becomes unmanageable.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Wouldn&#8217;t it be much nicer if

⌨️ 快捷键说明

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