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

📄 tij0083.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 2 页
字号:
seems to promote) is the perfect solution to a particular problem. This could
be termed an <A NAME="Index710"></A>&#8220;is-like-a&#8221;
relationship because the derived class is 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>like</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
the base class &#8211; it has the same fundamental interface &#8211; but it has
other features that require additional methods to implement:
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">While
this is also a useful and sensible approach (depending on the situation) it has
a drawback. The extended part of the interface in the derived class is not
available from the base class, so once you upcast you can&#8217;t call the new
methods:
</FONT><P></DIV><DIV ALIGN=CENTER><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you&#8217;re not upcasting in this case, it won&#8217;t bother you, but often
you&#8217;ll get into a situation in which you need to rediscover the exact
type of the object so you can access the extended methods of that type. The
following sections show how this is done.
</FONT><a name="_Toc375545343"></a><a name="_Toc408018559"></a><P></DIV>
<A NAME="Heading237"></A><H3 ALIGN=LEFT>
Downcasting
and run-time 
<P>type
identification
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Since
you lose the specific type information via an 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>upcast</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(moving up the inheritance hierarchy), it makes sense that to retrieve the type
information &#8211; that is, to move back down the inheritance hierarchy
&#8211; you use a <A NAME="Index711"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>downcast</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
However, you know an upcast is always safe; the base class cannot have a bigger
interface than the derived class, therefore every message you send through the
base class interface is guaranteed to be accepted. But with a downcast, you
don&#8217;t really know that a shape (for example) is actually a circle. It
could instead be a triangle or square or some other type.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
solve this problem there must be some way to guarantee that a downcast is
correct, so you won&#8217;t accidentally cast to the wrong type and then send a
message that the object can&#8217;t accept. This would be quite unsafe.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
some languages (like C++) you must perform a special operation in order to get
a type-safe downcast, but in Java 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>every
cast
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is checked! So even though it looks like you&#8217;re just performing an
ordinary parenthesized cast, at run time this cast is checked to ensure that it
is in fact the type you think it is. If it isn&#8217;t, you get a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ClassCastException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This act of checking types at run time is called <A NAME="Index712"></A><A NAME="Index713"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>run-time
type identification 
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(RTTI).
The following example demonstrates the behavior of RTTI:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: RTTI.java</font>
<font color="#009900">// Downcasting &amp; Run-Time Type</font>
<font color="#009900">// Identification (RTTI)</font>
<font color="#0000ff">import</font> java.util.*;

<font color="#0000ff">class</font> Useful {
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> f() {}
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> g() {}
}

<font color="#0000ff">class</font> MoreUseful <font color="#0000ff">extends</font> Useful {
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> f() {}
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> g() {}
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> u() {}
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> v() {}
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> w() {}
}

<font color="#0000ff">public</font> <font color="#0000ff">class</font> RTTI {
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    Useful[] x = {
      <font color="#0000ff">new</font> Useful(),
      <font color="#0000ff">new</font> MoreUseful()
    };
    x[0].f();
    x[1].g();
    <font color="#009900">// Compile-time: method not found in Useful:</font>
    <font color="#009900">//! x[1].u();</font>
    ((MoreUseful)x[1]).u(); <font color="#009900">// Downcast/RTTI</font>
    ((MoreUseful)x[0]).u(); <font color="#009900">// Exception thrown</font>
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">As
in the diagram, 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MoreUseful</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
extends the interface of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Useful</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
But since it&#8217;s inherited, it can also be upcast to a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Useful</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
You can see this happening in the initialization of the array 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>x</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">.
Since both objects in the array are of class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Useful</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can send the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>f(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>g(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods to both, and if you try to call 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>u(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(which exists only in 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MoreUseful</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
you&#8217;ll get a compile-time error message.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you want to access the extended interface of a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MoreUseful</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object, you can try to downcast. If it&#8217;s the correct type, it will be
successful. Otherwise, you&#8217;ll get a <A NAME="Index714"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ClassCastException</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
You don&#8217;t need to write any special code for this exception, since it
indicates a programmer error that could happen anywhere in a program.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There&#8217;s
more to RTTI than a simple cast. For example, there&#8217;s a way to see what
type you&#8217;re dealing with 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>before</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you try to downcast it. All of Chapter 11 is devoted to the study of different
aspects of Java run-time type identification.
</FONT><a name="_Toc375545344"></a><a name="_Toc408018560"></a><P></DIV>

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

⌨️ 快捷键说明

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