📄 tij0023.html
字号:
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">What’s
amazing about the code in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>doStuff( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is that somehow the right thing happens. Calling
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>draw( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Circle</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
causes different code to be executed than when calling
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>draw( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">for
a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Square</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
or a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Line</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but when the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>draw( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
message is sent to an anonymous
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Shape</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the correct behavior occurs based on the actual type that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Shape</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
handle happens to be connected to. This is amazing because when the Java
compiler is compiling the code for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>doStuff( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
it cannot know exactly what types it is dealing with. So ordinarily,
you’d expect it to end up calling the version of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>erase( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Shape</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>draw( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Shape</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and not for the specific
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Circle</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Square</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Line</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
And yet the right thing happens. Here’s how it works.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
you send a message to an object even though you don’t know what specific
type it is, and the right thing happens, that’s called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>polymorphism</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The process used by object-oriented programming languages to implement
polymorphism is called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>dynamic
binding
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The compiler and run-time system handle the details; all you need to know is
that it happens and more importantly how to design with it.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Some
languages require you to use a special keyword to enable dynamic binding. In
C++ this keyword is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>virtual</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
In Java, you never need to remember to add a keyword because functions are
automatically dynamically bound. So you can always expect that when you send a
message to an object, the object will do the right thing, even when upcasting
is involved.
</FONT><a name="_Toc375545197"></a><a name="_Toc408018394"></a><P></DIV>
<A NAME="Heading28"></A><H3 ALIGN=LEFT>
Abstract
base classes and interfaces
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Often
in a design, you want the base class to present
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>only</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
an interface for its derived classes. That is, you don’t want anyone to
actually create an object of the base class, only to upcast to it so that its
interface can be used. This is accomplished by making that class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>abstract
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">using
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword. If anyone tries to make an object of an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class, the compiler prevents them. This is a tool to enforce a particular design.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can also use the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword to describe a method that hasn’t been implemented yet – as
a stub indicating “here is an interface function for all types inherited
from this class, but at this point I don’t have any implementation for
it.” An
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">method
may be created only inside an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">class.
When the class is inherited, that method must be implemented, or the inherited
class becomes
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as well. Creating an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method allows you to put a method in an interface without being forced to
provide a possibly meaningless body of code for that method.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword takes the concept of an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class one step further by preventing any function definitions at all. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a very useful and commonly-used tool, as it provides the perfect separation
of interface and implementation. In addition, you can combine many interfaces
together, if you wish. (You cannot inherit from more than one regular
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract
class
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.)</FONT><a name="_Toc375545198"></a><a name="_Toc408018395"></a><P></DIV>
<HR><DIV ALIGN=LEFT><A NAME="fn5" HREF="#fnB5">[5]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
This uses the
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><I>Unified
Notation
</I></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">,
which will primarily be used in this book.
</FONT><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0022.html">Prev</a> | <a href="tij0024.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -