365 lines
316 KiB
HTML
365 lines
316 KiB
HTML
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||
|
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=0.8"/><title>13 Classes and Objects</title><link rel="stylesheet" type="text/css" href="../scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="../racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../doc-site.css" title="default"/><script type="text/javascript" src="../scribble-common.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../doc-site.js"></script><script type="text/javascript" src="../local-redirect/local-redirect.js"></script><script type="text/javascript" src="../local-redirect/local-user-redirect.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="doc-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_0");">▼</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">The Racket Guide</a></td></tr></table></div><div class="tocviewsublisttop" style="display: block;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1 </td><td><a href="intro.html" class="tocviewlink" data-pltdoc="x">Welcome to Racket</a></td></tr><tr><td align="right">2 </td><td><a href="to-scheme.html" class="tocviewlink" data-pltdoc="x">Racket Essentials</a></td></tr><tr><td align="right">3 </td><td><a href="datatypes.html" class="tocviewlink" data-pltdoc="x">Built-<wbr></wbr>In Datatypes</a></td></tr><tr><td align="right">4 </td><td><a href="scheme-forms.html" class="tocviewlink" data-pltdoc="x">Expressions and Definitions</a></td></tr><tr><td align="right">5 </td><td><a href="define-struct.html" class="tocviewlink" data-pltdoc="x">Programmer-<wbr></wbr>Defined Datatypes</a></td></tr><tr><td align="right">6 </td><td><a href="modules.html" class="tocviewlink" data-pltdoc="x">Modules</a></td></tr><tr><td align="right">7 </td><td><a href="contracts.html" class="tocviewlink" data-pltdoc="x">Contracts</a></td></tr><tr><td align="right">8 </td><td><a href="i_o.html" class="tocviewlink" data-pltdoc="x">Input and Output</a></td></tr><tr><td align="right">9 </td><td><a href="regexp.html" class="tocviewlink" data-pltdoc="x">Regular Expressions</a></td></tr><tr><td align="right">10 </td><td><a href="control.html" class="tocviewlink" data-pltdoc="x">Exceptions and Control</a></td></tr><tr><td align="right">11 </td><td><a href="for.html" class="tocviewlink" data-pltdoc="x">Iterations and Comprehensions</a></td></tr><tr><td align="right">12 </td><td><a href="match.html" class="tocviewlink" data-pltdoc="x">Pattern Matching</a></td></tr><tr><td align="right">13 </td><td><a href="classes.html" class="tocviewselflink" data-pltdoc="x">Classes and Objects</a></td></tr><tr><td align="right">14 </td><td><a href="units.html" class="tocviewlink" data-pltdoc="x">Units</a></td></tr><tr><td align="right">15 </td><td><a href="reflection.html" class="tocviewlink" data-pltdoc="x">Reflection and Dynamic Evaluation</a></td></tr><tr><td align="right">16 </td><td><a href="macros.html" class="tocviewlink" data-pltdoc="x">Macros</a></td></tr><tr><td align="right">17 </td><td><a href="languages.html" class="tocviewlink" data-pltdoc="x">Creating Languages</a></td></tr><tr><td align="right">18 </td><td><a href="concurrency.html" class="tocvie
|
||
|
just like a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span> expression:</p><blockquote class="leftindent"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" class="boxed RBoxed"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktVar">superclass-expr</span><span class="hspace"> </span><span class="RktVar">decl-or-expr</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p>The <span class="RktVar">superclass-expr</span> determines the superclass for the new
|
||
|
class. Each <span class="RktVar">decl-or-expr</span> is either a declaration related to
|
||
|
methods, fields, and initialization arguments, or it is an expression
|
||
|
that is evaluated each time that the class is instantiated. In other
|
||
|
words, instead of a method-like constructor, a class has
|
||
|
initialization expressions interleaved with field and method
|
||
|
declarations.</p><p>By convention, class names end with <span class="RktSym">%</span>. The built-in root class is
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span>. The following expression creates a class with
|
||
|
public methods <span class="RktSym">get-size</span>, <span class="RktSym">grow</span>, and <span class="RktSym">eat</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._init%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">init</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">initialization argument</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">current-size</span><span class="hspace"> </span><span class="RktSym">size</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">field</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">superclass initialization</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-size</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">current-size</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.
|
||
|
argument when instantiating the class through the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span> form:</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._init%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">init</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">]</span><span class="RktPn">)</span></p></blockquote><p>Of course, we can also name the class and its instance:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._init%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">init</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span><span class="RktPn">)</span></t
|
||
|
private field that starts out with the value of the <span class="RktSym">size</span>
|
||
|
initialization argument. Initialization arguments like <span class="RktSym">size</span>
|
||
|
are available only during class instantiation, so they cannot be
|
||
|
referenced directly from a method. The <span class="RktSym">current-size</span> field, in
|
||
|
contrast, is available to methods.</p><p>The <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span> expression in <span class="RktSym">fish%</span> invokes the
|
||
|
initialization of the superclass. In this case, the superclass is
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span>, which takes no initialization arguments and performs
|
||
|
no work; <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span> must be used, anyway, because a class must
|
||
|
always invoke its superclass’s initialization.</p><p>Initialization arguments, field declarations, and expressions such as
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span> can appear in any order within a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span>,
|
||
|
and they can be interleaved with method declarations. The relative
|
||
|
order of expressions in the class determines the order of evaluation
|
||
|
during instantiation. For example, if a field’s initial value requires
|
||
|
calling a method that works only after superclass initialization, then
|
||
|
the field declaration must be placed after the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span>
|
||
|
call. Ordering field and initialization declarations in this way helps
|
||
|
avoid imperative assignment. The relative order of method declarations
|
||
|
makes no difference for evaluation, because methods are fully defined
|
||
|
before a class is instantiated.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""methods"">13.1<tt> </tt><a name="(part._methods)"></a>Methods</h4><p>Each of the three <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span> declarations in
|
||
|
<span class="RktSym">fish%</span> introduces a new method. The declaration uses the same
|
||
|
syntax as a Racket function, but a method is not accessible as an
|
||
|
independent function. A call to the <span class="RktSym">grow</span> method of a
|
||
|
<span class="RktSym">fish%</span> object requires the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span> form:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span><span class="hspace"> </span><span class="RktSym">charlie</span><span class="hspace"> </span><span class="RktSym">grow</span><span class="hspace"> </span><span class="RktVal">6</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span><span class="hspace"> </span><span class="RktSym">charlie</span><span class="hspace"> </span><span class="RktSym">get-size</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">16</span></p></td></tr></table></blockquote><p>Within <span class="RktSym">fish%</span>, self methods can be called like functions,
|
||
|
because the method names are in scope. For example, the <span class="RktSym">eat</span>
|
||
|
method within <span class="RktSym">fish%</span> directly invokes the <span class="RktSym">grow</span>
|
||
|
method. Within a class, attempting to use a method name in any way
|
||
|
other than a method call results in a syntax error.</p><p>In some cases, a class must call methods that are supplied by the superclass
|
||
|
but not overridden. In that case, the class can use <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span>
|
||
|
with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._this%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">this</a></span> to access the method:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">hungry-fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat-more</span><span class="hspace"> </span><span class="RktSym">fish1</span><span class="hspace"> </span><span class="RktSym">fish2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._this%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">this</a></span><span class="hspace"> </span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">fish1</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span><span class="
|
||
|
which brings the method name into scope for a direct call:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">hungry-fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span><span class="hspace"> </span><span class="RktSym">eat</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat-more</span><span class="hspace"> </span><span class="RktSym">fish1</span><span class="hspace"> </span><span class="RktSym">fish2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">fish1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">fish2</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p> </p></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td></td></tr></table></td></tr></table></blockquote><p>With the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span> declaration, if <span class="RktSym">fish%</span> had not
|
||
|
provided an <span class="RktSym">eat</span> method, an error would be signaled in the
|
||
|
evaluation of the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> form for <span class="RktSym">hungry-fish%</span>. In
|
||
|
contrast, with <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span><span class="stt"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._this%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">this</a></span><span class="stt"> </span><span class="RktSym">....</span><span class="RktPn">)</span>, an error would not be
|
||
|
signaled until the <span class="RktSym">eat-more</span> method is called and the
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span> form is evaluated. For this reason, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span> is
|
||
|
preferred.</p><p>Another drawback of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span> is that it is less efficient than
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span>. Invocation of a method via <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span> involves
|
||
|
finding a method in the target object’s class at run time, making
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span> comparable to an interface-based method call in Java. In
|
||
|
contrast, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span>-based method invocations use an offset
|
||
|
within the class’s method table that is computed when the class is
|
||
|
created.</p><p>To achieve performance similar to <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span>-based method calls when
|
||
|
invoking a method from outside the method’s class, the programmer must use the
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._generic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">generic</a></span> form, which produces a class- and method-specific
|
||
|
<span style="font-style: italic">generic method</span> to be invoked with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send-generic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send-generic</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">get-fish-size</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._generic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">generic</a></span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktSym">get-size</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p> </p></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send-generic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send-generic</a></span><span class="hspace"> </span><span class="RktSym">charlie</span><span class="hspace"> </span><span class="RktSym">get-fish-size</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">16</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send-generic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send-generic</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span><span class="hspace"> </span><span class="RktSym">hungry-fish%</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktVal">32</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">get-fish-size</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">32</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send-generic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send-generic</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="Rk
|
||
|
method name to a location in the class’s method table. As illustrated
|
||
|
by the last example, sending through a generic method checks that its
|
||
|
argument is an instance of the generic’s class.</p><p>Whether a method is called directly within a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span>,
|
||
|
through a generic method,
|
||
|
or through <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span>, method overriding works in the usual way:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">picky-fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Foverride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/override</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">grow</span><span class="hspace"> </span><span class="RktSym">amt</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super</a></span><span class="hspace"> </span><span class="RktSym">grow</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3/4</span><span class="hspace"> </span><span class="RktSym">amt</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Foverride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/override</a></span> instead of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span>, because
|
||
|
<span class="RktSym">grow</span> is meant as an overriding declaration. If <span class="RktSym">grow</span>
|
||
|
had been declared with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span>, an error would have
|
||
|
been signaled when evaluating the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> expression, because
|
||
|
<span class="RktSym">fish%</span> already supplies <span class="RktSym">grow</span>.</p><p>Using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Foverride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/override</a></span> also allows the invocation of the
|
||
|
overridden method via a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super</a></span> call. For example, the
|
||
|
<span class="RktSym">grow</span> implementation in <span class="RktSym">picky-fish%</span> uses
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super</a></span> to delegate to the superclass implementation.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""initargs"">13.2<tt> </tt><a name="(part._initargs)"></a>Initialization Arguments</h4><p>Since <span class="RktSym">picky-fish%</span> declares no initialization arguments, any
|
||
|
initialization values supplied in <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span><span class="stt"> </span><span class="RktSym">picky-fish%</span><span class="stt"> </span><span class="RktSym">....</span><span class="RktPn">)</span> are
|
||
|
propagated to the superclass initialization, i.e., to <span class="RktSym">fish%</span>.
|
||
|
A subclass can supply additional initialization arguments for its
|
||
|
superclass in a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span> call, and such initialization
|
||
|
arguments take precedence over arguments supplied to <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span>. For
|
||
|
example, the following <span class="RktSym">size-10-fish%</span> class always generates
|
||
|
fish of size 10:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">size-10-fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p> </p></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span><span class="hspace"> </span><span class="RktSym">size-10-fish%</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">get-size</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">10</span></p></td></tr></table></td></tr></table></blockquote><p>In the case of <span class="RktSym">size-10-fish%</span>, supplying a <span class="RktSym">size</span>
|
||
|
initialization argument with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span> would result in an
|
||
|
initialization error; because the <span class="RktSym">size</span> in <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span>
|
||
|
takes precedence, a <span class="RktSym">size</span> supplied to <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span> would have
|
||
|
no target declaration.</p><p>An initialization argument is optional if the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> form
|
||
|
declares a default value. For example, the following <span class="RktSym">default-10-fish%</span>
|
||
|
class accepts a <span class="RktSym">size</span> initialization argument, but its value defaults to
|
||
|
10 if no value is supplied on instantiation:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">default-10-fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">fish%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._init%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">init</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktSym">size</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p> </p></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span><span class="hspace"> </span><span class="RktSym">default-10-fish%</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">(object:default-10-fish% ...)</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span><span class="hspace"> </span><span class="RktSym">default-10-fish%</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktVal">20</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">(object:default-10-fish% ...)</span></p></td></tr></table></td></tr></table></blockquote><p
|
||
|
<span class="RktSym">size</span> value as the <span class="RktSym">size</span> initialization argument to
|
||
|
the superclass.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""intnames"">13.3<tt> </tt><a name="(part._intnames)"></a>Internal and External Names</h4><p>The two uses of <span class="RktSym">size</span> in <span class="RktSym">default-10-fish%</span> expose the
|
||
|
double life of class-member identifiers. When <span class="RktSym">size</span> is the
|
||
|
first identifier of a bracketed pair in <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span> or
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span>, <span class="RktSym">size</span> is an <span style="font-style: italic">external name</span> that
|
||
|
is symbolically matched to an initialization argument in a class. When
|
||
|
<span class="RktSym">size</span> appears as an expression within
|
||
|
<span class="RktSym">default-10-fish%</span>, <span class="RktSym">size</span> is an <span style="font-style: italic">internal name</span>
|
||
|
that is lexically scoped. Similarly, a call to an inherited
|
||
|
<span class="RktSym">eat</span> method uses <span class="RktSym">eat</span> as an internal name, whereas a
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span> of <span class="RktSym">eat</span> uses <span class="RktSym">eat</span> as an external name.</p><p>The full syntax of the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> form allows a programmer to
|
||
|
specify distinct internal and external names for a class member. Since
|
||
|
internal names are local, they can be renamed to avoid shadowing or
|
||
|
conflicts. Such renaming is not frequently necessary, but workarounds
|
||
|
in the absence of renaming can be especially cumbersome.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Interfaces"">13.4<tt> </tt><a name="(part._.Interfaces)"></a>Interfaces</h4><p>Interfaces are useful for checking that an object or a class
|
||
|
implements a set of methods with a particular (implied) behavior.
|
||
|
This use of interfaces is helpful even without a static type system
|
||
|
(which is the main reason that Java has interfaces).</p><p>An interface in Racket is created using the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createinterface.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._interface%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">interface</a></span>
|
||
|
form, which merely declares the method names required to implement the
|
||
|
interface. An interface can extend other interfaces, which means that
|
||
|
implementations of the interface automatically implement the extended
|
||
|
interfaces.</p><blockquote class="leftindent"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" class="boxed RBoxed"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createinterface.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._interface%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">interface</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktVar">superinterface-expr</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVar">id</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p>To declare that a class implements an interface, the
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%252A%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class*</a></span> form must be used instead of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span>:</p><blockquote class="leftindent"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" class="boxed RBoxed"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%252A%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class*</a></span><span class="hspace"> </span><span class="RktVar">superclass-expr</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktVar">interface-expr</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVar">decl-or-expr</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p>For example, instead of forcing all fish classes to be derived from
|
||
|
<span class="RktSym">fish%</span>, we can define <span class="RktSym">fish-interface</span> and change the
|
||
|
<span class="RktSym">fish%</span> class to declare that it implements
|
||
|
<span class="RktSym">fish-interface</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">fish-interface</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createinterface.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._interface%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">interface</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">get-size</span><span class="hspace"> </span><span class="RktSym">grow</span><span class="hspace"> </span><span class="RktSym">eat</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%252A%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class*</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fish-interface</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>If the definition of <span class="RktSym">fish%</span> does not include
|
||
|
<span class="RktSym">get-size</span>, <span class="RktSym">grow</span>, and <span class="RktSym">eat</span> methods, then an
|
||
|
error is signaled in the evaluation of the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%252A%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class*</a></span> form,
|
||
|
because implementing the <span class="RktSym">fish-interface</span> interface requires
|
||
|
those methods.</p><p>The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objectutils.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._is-a%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">is-a?</a></span> predicate accepts an object as its first argument
|
||
|
and either a class or interface as its second argument. When given a
|
||
|
class, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objectutils.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._is-a%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">is-a?</a></span> checks whether the object is an instance of that
|
||
|
class or a derived class. When given an interface, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objectutils.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._is-a%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">is-a?</a></span>
|
||
|
checks whether the object’s class implements the interface. In
|
||
|
addition, the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objectutils.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._implementation%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">implementation?</a></span> predicate checks whether a
|
||
|
given class implements a given interface.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""inner"">13.5<tt> </tt><a name="(part._inner)"></a>Final, Augment, and Inner</h4><p>As in Java, a method in a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> form can be specified as
|
||
|
<span style="font-style: italic">final</span>, which means that a subclass cannot override the
|
||
|
method. A final method is declared using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._public-final%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">public-final</a></span> or
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._override-final%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">override-final</a></span>, depending on whether the declaration is for a
|
||
|
new method or an overriding implementation.</p><p>Between the extremes of allowing arbitrary overriding and disallowing
|
||
|
overriding entirely, the class system also supports Beta-style
|
||
|
<span style="font-style: italic">augmentable</span> methods [<a href="doc-bibliography.html#%28cite._.Goldberg04%29" data-pltdoc="x">Goldberg04</a>]. A method
|
||
|
declared with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._pubment%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">pubment</a></span> is like <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._public%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">public</a></span>, but the method
|
||
|
cannot be overridden in subclasses; it can be augmented only. A
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._pubment%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">pubment</a></span> method must explicitly invoke an augmentation (if any)
|
||
|
using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inner%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inner</a></span>; a subclass augments the method using
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augment%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augment</a></span>, instead of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._override%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">override</a></span>.</p><p>In general, a method can switch between augment and override modes in
|
||
|
a class derivation. The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augride</a></span> method specification
|
||
|
indicates an augmentation to a method where the augmentation is itself
|
||
|
overrideable in subclasses (though the superclass’s implementation
|
||
|
cannot be overridden). Similarly, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._overment%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">overment</a></span> overrides a method
|
||
|
and makes the overriding implementation augmentable.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""extnames"">13.6<tt> </tt><a name="(part._extnames)"></a>Controlling the Scope of External Names</h4><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Java’s access modifiers (like <a name="(idx._(gentag._4._(lib._scribblings/guide/guide..scrbl)))"></a><span class="stt">protected</span>)
|
||
|
play a role similar to <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span>, but
|
||
|
unlike in Java, Racket’s mechanism for controlling access
|
||
|
is based on lexical scope, not the inheritance hierarchy.</p></blockquote></blockquote></blockquote><p>As noted in <a href="classes.html#%28part._intnames%29" data-pltdoc="x">Internal and External Names</a>, class members have both
|
||
|
internal and external names. A member definition binds an internal
|
||
|
name locally, and this binding can be locally renamed. External
|
||
|
names, in contrast, have global scope by default, and a member
|
||
|
definition does not bind an external name. Instead, a member
|
||
|
definition refers to an existing binding for an external name, where
|
||
|
the member name is bound to a <span style="font-style: italic">member key</span>; a class ultimately
|
||
|
maps member keys to methods, fields, and initialization arguments.</p><p>Recall the <span class="RktSym">hungry-fish%</span> <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> expression:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">hungry-fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span><span class="hspace"> </span><span class="RktSym">eat</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat-more</span><span class="hspace"> </span><span class="RktSym">fish1</span><span class="hspace"> </span><span class="RktSym">fish2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">fish1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">fish2</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>During its evaluation, the <span class="RktSym">hungry-fish%</span> and <span class="RktSym">fish%</span>
|
||
|
classes refer to the same global binding of <span class="RktSym">eat</span>. At run
|
||
|
time, calls to <span class="RktSym">eat</span> in <span class="RktSym">hungry-fish%</span> are matched with
|
||
|
the <span class="RktSym">eat</span> method in <span class="RktSym">fish%</span> through the shared method
|
||
|
key that is bound to <span class="RktSym">eat</span>.</p><p>The default binding for an external name is global, but a
|
||
|
programmer can introduce an external-name binding with the
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span> form.</p><blockquote class="leftindent"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" class="boxed RBoxed"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span><span class="hspace"> </span><span class="RktVar">id</span><span class="hspace"> </span><span class="RktVar">member-key-expr</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p>In particular, by using <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._generate-member-key%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">generate-member-key</a></span><span class="RktPn">)</span> as the
|
||
|
<span class="RktSym">member-key-expr</span>, an external name can be localized for a
|
||
|
particular scope, because the generated member key is inaccessible
|
||
|
outside the scope. In other words, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span> gives
|
||
|
an external name a kind of package-private scope, but generalized from
|
||
|
packages to arbitrary binding scopes in Racket.</p><p>For example, the following <span class="RktSym">fish%</span> and <span class="RktSym">pond%</span> classes cooperate
|
||
|
via a <span class="RktSym">get-depth</span> method that is only accessible to the
|
||
|
cooperating classes:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._define-values%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-values</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fish%</span><span class="hspace"> </span><span class="RktSym">pond%</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">two mutually recursive classes</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span><span class="hspace"> </span><span class="RktSym">get-depth</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._generate-member-key%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">generate-member-key</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">fish%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">my-depth</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&ve
|
||
|
names. This separate namespace is implicitly used for the method name in
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span>, for initialization-argument names in <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span>, or for
|
||
|
the external name in a member definition. The special form
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span> provides access to the binding of an external name
|
||
|
in an arbitrary expression position: <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span><span class="stt"> </span><span class="RktSym">id</span><span class="RktPn">)</span>
|
||
|
produces the member-key binding of <span class="RktSym">id</span> in the current scope.</p><p>A member-key value is primarily used with a
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span> form. Normally, then,
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span><span class="stt"> </span><span class="RktSym">id</span><span class="RktPn">)</span> captures the method key of <span class="RktSym">id</span>
|
||
|
so that it can be communicated to a use of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span>
|
||
|
in a different scope. This capability turns out to be useful for
|
||
|
generalizing mixins, as discussed next.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Mixins"">13.7<tt> </tt><a name="(part._.Mixins)"></a>Mixins</h4><p>Since <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> is an expression form instead of a top-level
|
||
|
declaration as in Smalltalk and Java, a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> form can be
|
||
|
nested inside any lexical scope, including <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span>. The result
|
||
|
is a <a name="(tech._mixin)"></a><span style="font-style: italic">mixin</span>, i.e., a class extension that is parameterized
|
||
|
with respect to its superclass.</p><p>For example, we can parameterize the <span class="RktSym">picky-fish%</span> class over
|
||
|
its superclass to define <span class="RktSym">picky-mixin</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">picky-mixin</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Foverride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/override</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">grow</span><span class="hspace"> </span><span class="RktSym">amt</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super</a></span><span class="hspace"> </span><span class="RktSym">grow</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3/4</span><span class="hspace"> </span><span class="RktSym">amt</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">picky-fish%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">picky-mixin</span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>Many small differences between Smalltalk-style classes and Racket
|
||
|
classes contribute to the effective use of mixins. In particular, the
|
||
|
use of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Foverride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/override</a></span> makes explicit that
|
||
|
<span class="RktSym">picky-mixin</span> expects a class with a <span class="RktSym">grow</span> method. If
|
||
|
<span class="RktSym">picky-mixin</span> is applied to a class without a <span class="RktSym">grow</span>
|
||
|
method, an error is signaled as soon as <span class="RktSym">picky-mixin</span> is
|
||
|
applied.</p><p>Similarly, a use of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span> enforces a “method existence”
|
||
|
requirement when the mixin is applied:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">hungry-mixin</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span><span class="hspace"> </span><span class="RktSym">eat</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat-more</span><span class="hspace"> </span><span class="RktSym">fish1</span><span class="hspace"> </span><span class="RktSym">fish2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">fish1</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">fish2</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>The advantage of mixins is that we can easily combine them to create
|
||
|
new classes whose implementation sharing does not fit into a
|
||
|
single-inheritance hierarchy—<wbr></wbr>without the ambiguities associated with
|
||
|
multiple inheritance. Equipped with <span class="RktSym">picky-mixin</span> and
|
||
|
<span class="RktSym">hungry-mixin</span>, creating a class for a hungry, yet picky fish
|
||
|
is straightforward:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">picky-hungry-fish%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">hungry-mixin</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">picky-mixin</span><span class="hspace"> </span><span class="RktSym">fish%</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>The use of keyword initialization arguments is critical for the easy
|
||
|
use of mixins. For example, <span class="RktSym">picky-mixin</span> and
|
||
|
<span class="RktSym">hungry-mixin</span> can augment any class with suitable <span class="RktSym">eat</span>
|
||
|
and <span class="RktSym">grow</span> methods, because they do not specify initialization
|
||
|
arguments and add none in their <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span> expressions:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">person%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._init%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">init</a></span><span class="hspace"> </span><span class="RktSym">name</span><span class="hspace"> </span><span class="RktSym">age</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">food</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">grow</span><span class="hspace"> </span><span class="RktSym">amt</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace
|
||
|
lexically scoped identifiers) makes mixin use convenient. Applying
|
||
|
<span class="RktSym">picky-mixin</span> to <span class="RktSym">person%</span> works because the names
|
||
|
<span class="RktSym">eat</span> and <span class="RktSym">grow</span> match, without any a priori declaration
|
||
|
that <span class="RktSym">eat</span> and <span class="RktSym">grow</span> should be the same method in
|
||
|
<span class="RktSym">fish%</span> and <span class="RktSym">person%</span>. This feature is a potential
|
||
|
drawback when member names collide accidentally; some accidental
|
||
|
collisions can be corrected by limiting the scope external names, as
|
||
|
discussed in <a href="classes.html#%28part._extnames%29" data-pltdoc="x">Controlling the Scope of External Names</a>.</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Mixins_and_Interfaces"">13.7.1<tt> </tt><a name="(part._.Mixins_and_.Interfaces)"></a>Mixins and Interfaces</h5><p>Using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objectutils.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._implementation%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">implementation?</a></span>, <span class="RktSym">picky-mixin</span> could require
|
||
|
that its base class implements <span class="RktSym">grower-interface</span>, which could
|
||
|
be implemented by both <span class="RktSym">fish%</span> and <span class="RktSym">person%</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">grower-interface</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createinterface.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._interface%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">interface</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">grow</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">picky-mixin</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=when_unless.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._unless%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">unless</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objectutils.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._implementation%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">implementation?</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktSym">grower-interface</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=exns.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._error%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">error</a></span><span class="hspace"> </span><span class="RktVal">"picky-mixin: not a grower-interface class"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>Another use of interfaces with a mixin is to tag classes generated by
|
||
|
the mixin, so that instances of the mixin can be recognized. In other
|
||
|
words, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objectutils.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._is-a%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">is-a?</a></span> cannot work on a mixin represented as a
|
||
|
function, but it can recognize an interface (somewhat like a
|
||
|
<span style="font-style: italic">specialization interface</span>) that is consistently implemented
|
||
|
by the mixin. For example, classes generated by <span class="RktSym">picky-mixin</span>
|
||
|
could be tagged with <span class="RktSym">picky-interface</span>, enabling the
|
||
|
<span class="RktSym">is-picky?</span> predicate:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">picky-interface</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createinterface.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._interface%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">interface</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">picky-mixin</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=when_unless.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._unless%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">unless</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objectutils.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._implementation%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">implementation?</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktSym">grower-interface</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=exns.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._error%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">error</a></span><span class="hspace"> </span><span class="RktVal">"picky-mixin: not a grower-interface class"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%252A%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class*</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">picky-interface</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&
|
||
|
implementing mixins, including the use of interfaces for the domain
|
||
|
and range of the mixin, the class system provides a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=mixins.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._mixin%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">mixin</a></span>
|
||
|
macro:</p><blockquote class="leftindent"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" class="boxed RBoxed"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=mixins.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._mixin%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">mixin</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktVar">interface-expr</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktVar">interface-expr</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVar">decl-or-expr</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></blockquote><p>The first set of <span class="RktSym">interface-expr</span>s determines the domain of the
|
||
|
mixin, and the second set determines the range. That is, the expansion
|
||
|
is a function that tests whether a given base class implements the
|
||
|
first sequence of <span class="RktSym">interface-expr</span>s and produces a class that
|
||
|
implements the second sequence of <span class="RktSym">interface-expr</span>s. Other
|
||
|
requirements, such as the presence of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span>ed methods in
|
||
|
the superclass, are then checked for the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span> expansion of
|
||
|
the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=mixins.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._mixin%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">mixin</a></span> form. For example:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">choosy-interface</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createinterface.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._interface%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">interface</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">choose?</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">hungry-interface</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createinterface.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._interface%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">interface</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">eat</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">choosy-eater-mixin</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=mixins.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._mixin%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">mixin</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">choosy-interface</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">hungry-interface</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&ver
|
||
|
can also augment methods, introduce augment-only methods, add an
|
||
|
overrideable augmentation, and add an augmentable override —<wbr></wbr> all of
|
||
|
the things that a class can do (see <a href="classes.html#%28part._inner%29" data-pltdoc="x">Final, Augment, and Inner</a>).</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""parammixins"">13.7.3<tt> </tt><a name="(part._parammixins)"></a>Parameterized Mixins</h5><p>As noted in <a href="classes.html#%28part._extnames%29" data-pltdoc="x">Controlling the Scope of External Names</a>, external names can be bound with
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span>. This facility allows a mixin to be
|
||
|
generalized with respect to the methods that it defines and uses. For
|
||
|
example, we can parameterize <span class="RktSym">hungry-mixin</span> with respect to the
|
||
|
external member key for <span class="RktSym">eat</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-hungry-mixin</span><span class="hspace"> </span><span class="RktSym">eat-method-key</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span><span class="hspace"> </span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">eat-method-key</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=mixins.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._mixin%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">mixin</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span><span class="hspace"> </span><span class="RktSym">eat</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat-more</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>To obtain a particular hungry-mixin, we must apply this function to a
|
||
|
member key that refers to a suitable
|
||
|
<span class="RktSym">eat</span> method, which we can obtain using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym">make-hungry-mixin</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span><span class="hspace"> </span><span class="RktSym">eat</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span><span class="hspace"> </span><span class="RktSym">....</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">yum</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>Above, we apply <span class="RktSym">hungry-mixin</span> to an anonymous class that provides
|
||
|
<span class="RktSym">eat</span>, but we can also combine it with a class that provides
|
||
|
<span class="RktSym">chomp</span>, instead:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym">make-hungry-mixin</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span><span class="hspace"> </span><span class="RktSym">chomp</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span><span class="hspace"> </span><span class="RktSym">....</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">chomp</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">yum</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Traits"">13.8<tt> </tt><a name="(part._.Traits)"></a>Traits</h4><p>A <span style="font-style: italic">trait</span> is similar to a mixin, in that it encapsulates a set
|
||
|
of methods to be added to a class. A trait is different from a mixin
|
||
|
in that its individual methods can be manipulated with trait operators
|
||
|
such as <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528def._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-sum%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">trait-sum</a></span> (merge the methods of two traits), <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-exclude%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-exclude</a></span>
|
||
|
(remove a method from a trait), and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-alias%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-alias</a></span> (add a copy of a
|
||
|
method with a new name; do not redirect any calls to the old name).</p><p>The practical difference between mixins and traits is that two traits
|
||
|
can be combined, even if they include a common method and even if
|
||
|
neither method can sensibly override the other. In that case, the
|
||
|
programmer must explicitly resolve the collision, usually by aliasing
|
||
|
methods, excluding methods, and merging a new trait that uses the
|
||
|
aliases.</p><p>Suppose our <span class="RktSym">fish%</span> programmer wants to define two class
|
||
|
extensions, <span class="RktSym">spots</span> and <span class="RktSym">stripes</span>, each of which
|
||
|
includes a <span class="RktSym">get-color</span> method. The fish’s spot color should not
|
||
|
override the stripe color nor vice versa; instead, a
|
||
|
<span class="RktSym">spots+stripes-fish%</span> should combine the two colors, which is
|
||
|
not possible if <span class="RktSym">spots</span> and <span class="RktSym">stripes</span> are implemented as
|
||
|
plain mixins. If, however, <span class="RktSym">spots</span> and <span class="RktSym">stripes</span> are
|
||
|
implemented as traits, they can be combined. First, we alias
|
||
|
<span class="RktSym">get-color</span> in each trait to a non-conflicting name. Second,
|
||
|
the <span class="RktSym">get-color</span> methods are removed from both and the traits
|
||
|
with only aliases are merged. Finally, the new trait is used to create
|
||
|
a class that introduces its own <span class="RktSym">get-color</span> method based on the
|
||
|
two aliases, producing the desired <span class="RktSym">spots+stripes</span> extension.</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Traits_as_Sets_of_Mixins"">13.8.1<tt> </tt><a name="(part._.Traits_as_.Sets_of_.Mixins)"></a>Traits as Sets of Mixins</h5><p>One natural approach to implementing traits in Racket is as a set
|
||
|
of mixins, with one mixin per trait method. For example, we might
|
||
|
attempt to define the spots and stripes traits as follows, using
|
||
|
association lists to represent sets:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">spots-trait</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._cons%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">get-color</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">%</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-color</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">black</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-exclude%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-exclude</a></span> as simple manipulations; unfortunately, it does
|
||
|
not support the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-alias%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-alias</a></span> operator. Although a mixin can be
|
||
|
duplicated in the association list, the mixin has a fixed method name,
|
||
|
e.g., <span class="RktSym">get-color</span>, and mixins do not support a method-rename
|
||
|
operation. To support <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-alias%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-alias</a></span>, we must parameterize the
|
||
|
mixins over the external method name in the same way that <span class="RktSym">eat</span>
|
||
|
was parameterized in <a href="classes.html#%28part._parammixins%29" data-pltdoc="x">Parameterized Mixins</a>.</p><p>To support the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-alias%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-alias</a></span> operation, <span class="RktSym">spots-trait</span>
|
||
|
should be represented as:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">spots-trait</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._cons%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span><span class="hspace"> </span><span class="RktSym">get-color</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-color-key</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span><span class="hspace"> </span><span class="RktSym">get-color</span><span class="hspace"> </span><span class="RktSym">get-color-key</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">
|
||
|
to <span class="RktSym">get-trait-color</span> and the <span class="RktSym">get-color</span> method is
|
||
|
removed, the resulting trait is the same as</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._cons%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span><span class="hspace"> </span><span class="RktSym">get-trait-color</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-color-key</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define-member-name%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-member-name</a></span><span class="hspace"> </span><span class="RktSym">get-color</span><span class="hspace"> </span><span class="RktSym">get-color-key</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktS
|
||
|
class, we use <span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528def._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-%7E3emixin%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">trait->mixin</a></span><span class="stt"> </span><span class="RktVar">T</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVar">C</span><span class="RktPn">)</span>. The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528def._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-%7E3emixin%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">trait->mixin</a></span>
|
||
|
function supplies each mixin of <span class="RktVar">T</span> with the key for the mixin’s
|
||
|
method and a partial extension of <span class="RktVar">C</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528def._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-%7E3emixin%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">trait->mixin</a></span><span class="hspace"> </span><span class="RktSym">T</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">C</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Flist..rkt%2529._foldr%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">foldr</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._cdr%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">cdr</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._car%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">car</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">C</span><span class="hspace"> </span><span class="RktSym">T</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>Thus, when the trait above is combined with other traits and then
|
||
|
applied to a class, the use of <span class="RktSym">get-color</span> becomes a reference
|
||
|
to the external name <span class="RktSym">get-trait-color</span>.</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Inherit_and_Super_in_Traits"">13.8.2<tt> </tt><a name="(part._.Inherit_and_.Super_in_.Traits)"></a>Inherit and Super in Traits</h5><p>This first implementation of traits supports <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-alias%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-alias</a></span>, and it
|
||
|
supports a trait method that calls itself, but it does not support
|
||
|
trait methods that call each other. In particular, suppose that a spot-fish’s
|
||
|
market value depends on the color of its spots:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">spots-trait</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._cons%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span><span class="hspace"> </span><span class="RktSym">get-color</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._cons%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._member-name-key%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">member-name-key</a></span><span class="hspace"> </span><span class="RktSym">get-price</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-price</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> &
|
||
|
<span class="RktSym">get-color</span> is not in scope for the <span class="RktSym">get-price</span>
|
||
|
mixin. Indeed, depending on the order of mixin application when the
|
||
|
trait is applied to a class, the <span class="RktSym">get-color</span> method may not be
|
||
|
available when <span class="RktSym">get-price</span> mixin is applied to the class.
|
||
|
Therefore adding an <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span><span class="stt"> </span><span class="RktSym">get-color</span><span class="RktPn">)</span> declaration to the
|
||
|
<span class="RktSym">get-price</span> mixin does not solve the problem.</p><p>One solution is to require the use of <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span><span class="stt"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._this%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">this</a></span><span class="stt"> </span><span class="RktSym">get-color</span><span class="RktPn">)</span> in
|
||
|
methods such as <span class="RktSym">get-price</span>. This change works because
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._send%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">send</a></span> always delays the method lookup until the method call is
|
||
|
evaluated. The delayed lookup is more expensive than a direct call,
|
||
|
however. Worse, it also delays checking whether a <span class="RktSym">get-color</span> method
|
||
|
even exists.</p><p>A second, effective, and efficient solution is to change the encoding
|
||
|
of traits. Specifically, we represent each method as a pair of mixins:
|
||
|
one that introduces the method and one that implements it. When a
|
||
|
trait is applied to a class, all of the method-introducing mixins are
|
||
|
applied first. Then the method-implementing mixins can use
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span> to directly access any introduced method.</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">spots-trait</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">local-member-name-key</span><span class="hspace"> </span><span class="RktSym">get-color</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-color</span><span class="hspace"> </span><span class="RktSym">get-price</span><span class="hspace"> </span><span class="RktSym">%</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">%</span><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-color</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=void.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._void%2529%2529&version=8.6" class="RktValLink Sq" data
|
||
|
a new name, but it does not change any references to the old method.</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""The_trait_Form"">13.8.3<tt> </tt><a name="(part._.The_trait_.Form)"></a>The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait</a></span> Form</h5><p>The general-purpose trait pattern is clearly too complex for a
|
||
|
programmer to use directly, but it is easily codified in a
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait</a></span> macro:</p><blockquote class="leftindent"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" class="boxed RBoxed"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait</a></span><span class="hspace"> </span><span class="RktVar">trait-clause</span><span class="hspace"> </span><span class="RktMeta">...</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p>The <span class="RktSym">id</span>s in the optional <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span> clause are available for direct
|
||
|
reference in the method <span class="RktSym">expr</span>s, and they must be supplied
|
||
|
either by other traits or the base class to which
|
||
|
the trait is ultimately applied.</p><p>Using this form in conjunction with trait operators such as
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528def._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-sum%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">trait-sum</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-exclude%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-exclude</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-alias%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait-alias</a></span>, and
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528def._%2528%2528lib._racket%252Ftrait..rkt%2529._trait-%7E3emixin%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">trait->mixin</a></span>, we can implement <span class="RktSym">spots-trait</span> and
|
||
|
<span class="RktSym">stripes-trait</span> as desired.</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">spots-trait</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-color</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">black</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-price</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-color</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=stx-patterns.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fstxcase-scheme..rkt%2529._......%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">stripes-trait</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=trait.html%23%2528form._%2528%2528lib._racket%252Ftrait..rkt%2529._trait%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">trait</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=referen
|
||
|
may wish to protect parts of a given class with contracts. For this,
|
||
|
the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._class%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class/c</a></span> form is used. The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._class%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class/c</a></span> form has many
|
||
|
subforms, which describe two types of contracts on fields and methods:
|
||
|
those that affect uses via instantiated objects and those that affect
|
||
|
subclasses.</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""External_Class_Contracts"">13.9.1<tt> </tt><a name="(part._.External_.Class_.Contracts)"></a>External Class Contracts</h5><p>In its simplest form, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._class%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class/c</a></span> protects the public fields and methods
|
||
|
of objects instantiated from the contracted class. There is also an
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._object%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">object/c</a></span> form that can be used to similarly protect the public fields
|
||
|
and methods of a particular object. Take the following definition of
|
||
|
<span class="RktSym">animal%</span>, which uses a public field for its <span class="RktSym">size</span> attribute:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">animal%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._object%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">object%</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._field%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">field</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Fpublic%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/public</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">food</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.
|
||
|
should return a positive number. Also, if the <span class="RktSym">size</span> field is set,
|
||
|
it should be assigned a positive number. Finally, the <span class="RktSym">eat</span> method
|
||
|
should receive an argument which is an object with a <span class="RktSym">size</span> field
|
||
|
that contains a positive number. To ensure these conditions, we will define
|
||
|
the <span class="RktSym">animal%</span> class with an appropriate contract:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">positive/c</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._and%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">and/c</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._positive%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">positive?</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">edible/c</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._object%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">object/c</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._field%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">field</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktSym">positive/c</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fregion..rkt%2529._define%252Fcontract%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/contract</a></span><span class="hspace"> </span><span class="RktSym">animal%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._class%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class/c</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/lo
|
||
|
do not need to describe any requirements for the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._this%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">this</a></span> parameter.
|
||
|
Now that we have our contracted class, we can see that the contracts
|
||
|
on both <span class="RktSym">size</span> and <span class="RktSym">eat</span> are enforced:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">bob</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">new</a></span><span class="hspace"> </span><span class="RktSym">animal%</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._set-field%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set-field!</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktSym">bob</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._get-field%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">get-field</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktSym">bob</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">3</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=ivaraccess.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._set-field%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set-field!</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktSym">bob</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">large</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">animal%: contract violation</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">expected: positive/c</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">given: 'large</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">in: the size field in</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">(class/c</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">(eat</span></p></td></tr><tr><td><p><span class="R
|
||
|
external method contracts are only enforced when the target of dynamic
|
||
|
dispatch is the method implementation of the contracted class, which
|
||
|
lies within the contract boundary. Overriding that implementation, and
|
||
|
thus changing the target of dynamic dispatch, will mean that the contract
|
||
|
is no longer enforced for clients, since accessing the method no longer
|
||
|
crosses the contract boundary. Unlike external method contracts, external
|
||
|
field contracts are always enforced for clients of subclasses, since fields
|
||
|
cannot be overridden or shadowed.</p><p>Second, these contracts do not restrict subclasses of <span class="RktSym">animal%</span>
|
||
|
in any way. Fields and methods that are inherited and used by subclasses
|
||
|
are not checked by these contracts, and uses of the superclass’s methods
|
||
|
via <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super</a></span> are also unchecked. The following example illustrates
|
||
|
both caveats:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">large-animal%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._class%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class</a></span><span class="hspace"> </span><span class="RktSym">animal%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=objcreation.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super-new%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super-new</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit-field%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit-field</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">large</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._define%252Foverride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/override</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktSym">food</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._display%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">display</a></span><span class="hspace"> </span><span class="RktVal">"Nom nom nom"</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Byte_and_String_Output.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._newline%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">newline</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="Rkt
|
||
|
<span class="RktSym">elephant</span> blames <span class="RktSym">animal%</span> for the contract violation.
|
||
|
This blame is correct, but unfair to the <span class="RktSym">animal%</span> class,
|
||
|
as we have not yet provided it with a method for protecting itself from
|
||
|
subclasses. To this end we add internal class contracts, which
|
||
|
provide directives to subclasses for how they may access and override
|
||
|
features of the superclass. This distinction between external and internal
|
||
|
class contracts allows for weaker contracts within the class hierarchy, where
|
||
|
invariants may be broken internally by subclasses but should be enforced
|
||
|
for external uses via instantiated objects.</p><p>As a simple example of what kinds of protection are available, we provide
|
||
|
an example aimed at the <span class="RktSym">animal%</span> class that uses all the applicable
|
||
|
forms:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._class%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class/c</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._field%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">field</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktSym">positive/c</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit-field%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit-field</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktSym">positive/c</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._-%7E3em%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span>m</a></span><span class="hspace"> </span><span class="RktSym">edible/c</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=void.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._void%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">void?</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._-%7E3em%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span>m</a></span><span class="hspace"> </span><span class="RktSym">edible/c</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=void.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._void%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">void?</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktP
|
||
|
are protected as before, but also ensure that subclasses of <span class="RktSym">animal%</span>
|
||
|
only store appropriate values within the <span class="RktSym">size</span> field and use
|
||
|
the implementation of <span class="RktSym">size</span> from <span class="RktSym">animal%</span> appropriately.
|
||
|
These contract forms only affect uses within the class hierarchy, and only
|
||
|
for method calls that cross the contract boundary.</p><p>That means that <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inherit%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inherit</a></span> will only affect subclass uses of a method
|
||
|
until a subclass overrides that method, and that <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._override%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">override</a></span> only
|
||
|
affects calls from the superclass into a subclass’s overriding implementation
|
||
|
of that method. Since these only affect internal uses, the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._override%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">override</a></span>
|
||
|
form does not automatically enter subclasses into obligations when objects of
|
||
|
those classes are used. Also, use of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._override%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">override</a></span> only makes sense, and
|
||
|
thus can only be used, for methods where no Beta-style augmentation has taken
|
||
|
place. The following example shows this difference:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fregion..rkt%2529._define%252Fcontract%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/contract</a></span><span class="hspace"> </span><span class="RktSym">sloppy-eater%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._class%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class/c</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._-%7E3em%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span>m</a></span><span class="hspace"> </span><span class="RktSym">edible/c</span><span class="hspace"> </span><span class="RktSym">edible/c</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=begin.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._begin%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">begin</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fregion..rkt%2529._define%252Fcontract%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/contract</a></span><span class="hspace"> </span><span class="RktSym">glutton%</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._class%252Fc%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">class/c</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._override%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">override</a></span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">eat</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Object_and_Class_Contracts.html%23%2528form._%2528%2528lib._racket%252Fclass..rkt%2529._-%7E3em%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span>m</a></span><span class="hspace"> </span><span class="RktSym">edible/c</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&a
|
||
|
similar forms for Beta-style augmentable methods. The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inner%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inner</a></span>
|
||
|
form describes to the subclass what is expected from augmentations of
|
||
|
a given method. Both <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augment%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augment</a></span> and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augride</a></span> tell the
|
||
|
subclass that the given method is a method which has been augmented and
|
||
|
that any calls to the method in the subclass will dynamically
|
||
|
dispatch to the appropriate implementation in the superclass. Such
|
||
|
calls will be checked according to the given contract. The two forms
|
||
|
differ in that use of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augment%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augment</a></span> signifies that subclasses can
|
||
|
augment the given method, whereas use of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augride</a></span> signifies that
|
||
|
subclasses must override the current augmentation instead.</p><p>This means that not all forms can be used at the same time. Only one of the
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._override%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">override</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augment%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augment</a></span>, and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augride</a></span> forms can be used
|
||
|
for a given method, and none of these forms can be used if the given method
|
||
|
has been finalized. In addition, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._super%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">super</a></span> can be specified for a given
|
||
|
method only if <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augride</a></span> or <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._override%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">override</a></span> can be specified.
|
||
|
Similarly, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._inner%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">inner</a></span> can be specified only if <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augment%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augment</a></span> or
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=createclass.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fclass-internal..rkt%2529._augride%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">augride</a></span> can be specified.</p><div class="navsetbottom"><span class="navleft"><form class="searchform"><input class="searchbox" id="searchbox" type="text" tabindex="1" placeholder="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, "8.6", "../");"/></form> <a href="https://download.racket-lang.org/releases/8.6/doc/index.html" title="up to the documentation top" data-pltdoc="x" onclick="return GotoPLTRoot("8.6");">top</a><span class="tocsettoggle"> <a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright"> <a href="match.html" title="backward to "12 Pattern Matching"" data-pltdoc="x">← prev</a> <a href="index.html" title="up to "The Racket Guide"" data-pltdoc="x">up</a> <a href="units.html" title="forward to "14 Units (Components)"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html>
|