



<html>
<head>
  <title>javabog.dk -  - Videreg&aring;ende OOP</title>
  <link rev="stylesheet" type="text/css" href="../typografi.css">
  <meta name="description" content="Lærebog i Java. Af Jacob Nordfalk. Udkommet hos Forlaget Globe">
  <meta name="keywords" content="designmønster, programmering, OOP, objekter, klasser, objektorienteret programmering, Java, JSP, lærebog, UML, IT">
</head>
<body bgcolor="#ffffff">



<a href='http://javabog.dk/'>javabog.dk</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel14.jsp'>&lt;&lt; forrige</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='indhold.jsp'>indhold</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel16.jsp'>n&aelig;ste &gt;&gt;</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kode/'>programeksempler</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='../index_VP.html'>om bogen</a>

<H1 CLASS="western" STYLE="">15 <a name='afsn15'></a>Videreg&aring;ende
OOP</H1>
<DIV ID="Indholdsfortegnelse9">
  <P STYLE="margin-top: 0.3cm; margin-bottom: 0cm"><BR>
  </P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.1
  Arv  228</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.1.1
  Holdninger til arv  228</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.1.2
  Modstrid mellem holdningerne  228</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.1.3
  &Oslash;velse  231</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.1.4
  Nedarvinger, hvor funktionaliteten ikke udvides, men begr&aelig;nses  231</FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.2
  Delegering (i stedet for arv)  232</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.2.1
  At skjule nogle metoder  232</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.2.2
  Modellering af roller  234</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.2.3
  Resum&eacute; og konklusion  236</FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.3
  Specific&eacute;r funktionalitet i et interface  236</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.3.1
  Repetition af interfaces  236</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.3.2
  Eksempel: Stak  237</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.3.3
  Eksempel: Collections-klasserne  238</FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.4
  Konstanterkl&aelig;ringer i et interface  239</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.5
  Markeringsinterface  239</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.6
  Ansvarsomr&aring;der  240</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.6.1
  Eksempel p&aring; tildeling af ansvarsomr&aring;der  240</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.6.2
  Ekspert  242</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.6.3
  Skaber  242</FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.7
  Lav kobling og h&oslash;j koh&aelig;sion  243</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.7.1
  Lav kobling  243</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.7.2
  H&oslash;j koh&aelig;sion  243</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.7.3
  Indkapsling  244</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.7.4
  Indkapsling og pakker  244</FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.8
  GRASP  245</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>15.9
  Introduktion til designm&oslash;nstre  245</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">15.9.1
  Designm&oslash;nstre ber&oslash;rt i de f&oslash;lgende kapitler  245</FONT></FONT></P>
</DIV>


<P CLASS="western" STYLE=""><SPAN LANG="da-DK">I
dette kapitel vil vi diskutere nogle af de begreber og tankegange,
der kan v&aelig;re inspirerende, n&aring;r man har tilegnet sig en
grundl&aelig;ggende viden og erfaring inden for objektorienteret
programmering. Kapitlet er struktureret i emner, som kan l&aelig;ses
nogenlunde uafh&aelig;ngigt af hinanden. Emnerne er beregnet som
inspiration til eftertanke snarere end faste anvisninger, der altid
b&oslash;r f&oslash;lges. </SPAN>
</P>
<P CLASS="western">Hvor det er relevant, beskrives nogle teknikker,
der er specifikke i Java, og hvad man i stedet ville g&oslash;re i
C++.</P>
<H2 CLASS="western">15.1 <a name='afsn15.1'></a>Arv</SPAN></H2>
<H3 CLASS="western">15.1.1 <a name='afsn15.1.1'></a>Holdninger til arv</H3>
<P CLASS="western">Ved nedarving fra en klasse til en anden vil
nedarvingen overtage (&quot;arve&quot;) alle variabler og metoder fra
superklassen. Der er dog flere mulige holdninger til, hvordan arv
skal bruges.</P>
<P CLASS="western"><SPAN LANG="da-DK"><B>Den koden&aelig;re</B>,
&quot;amerikanske&quot;<A CLASS="sdfootnoteanc" NAME="sdfootnote1anc" HREF="#sdfootnote1sym"><SUP>1</SUP></A>:
<I>Arv bruges til at genbruge variabler og metoder. </I>Hvis to
klasser har f&aelig;lles variabler eller metoder, b&oslash;r man lave
en f&aelig;lles superklasse, der tager vare p&aring; de ting, der er
f&aelig;lles. </SPAN>
</P>
<P CLASS="western"><SPAN LANG="da-DK"><B>Den analytiske</B>,
&quot;skandinaviske&quot;: <I>Arv repr&aelig;senterer en
er-en-relation</I>, og nedarving b&oslash;r ske mellem klasser, n&aring;r
de begreber, som de st&aring;r for, har en 'er-en'-relation til
hinanden.</SPAN></P>
<P CLASS="western">Den koden&aelig;re holdning, at arv bliver
betragtet som en m&aring;de at spare kode p&aring;, er en
'nedefra-og-op'-strategi, hvor der f&oslash;rst og fremmest
programmeres og hvor klasserelationer som arv senere dukker frem som
'konsekvenser' af programmeringen. I  de mere udbredte
programmeringssprog, som C og Pascal, var denne holdning dominerende
i 1980'erne, lige da klasser og objekter var blevet indf&oslash;rt i
disse sprog. 
</P>
<P CLASS="western">Senere, da discipliner som objektorienteret
analyse og design voksede frem, blev den analytiske
'oppefra-og-ned'-m&aring;de at anskue tingene p&aring; mere popul&aelig;r.</P>
<P CLASS="western">Ofte vil disse tankegange give de samme
nedarvingsrelationer, s&aring; det kan v&aelig;re sv&aelig;rt
umiddelbart at forst&aring;, hvilken forskel det skulle g&oslash;re.</P>
<H3 CLASS="western">15.1.2 <a name='afsn15.1.2'></a>Modstrid mellem holdningerne</H3>
<P CLASS="western">For at tage et klassisk eksempel, hvor disse to
tankegange kommer i indbyrdes modstrid, s&aring; betragt et
tegneprogram med forskellige figurer: Punkter, linjer, rektangler,
trekanter, firkanter, polygoner, cirkler, ovaler osv. I f&oslash;rste
omgang defineres f&oslash;lgende klasser:</P>
<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0>
  <COL*>
  <COL*>
  <COL*>
  <THEAD>
    <TR VALIGN=TOP>
      <TH>
        <P CLASS="western">Klasse</P>
      </TH>
      <TH>
        <P CLASS="western">variabler</P>
      </TH>
      <TH>
        <P CLASS="western">metoder</P>
      </TH>
    </TR>
  </THEAD>
  <TBODY>
    <TR VALIGN=TOP>
      <TD>
        <P CLASS="western">Punkt</P>
      </TD>
      <TD>
        <P CLASS="western">int x, y</P>
      </TD>
      <TD>
        <P CLASS="western">void tegn() <BR>void flytTil(x,y)</P>
      </TD>
    </TR>
    <TR VALIGN=TOP>
      <TD>
        <P CLASS="western">Linje</P>
      </TD>
      <TD>
        <P CLASS="western">int x, y, dx, dy</P>
      </TD>
      <TD>
        <P CLASS="western">void tegn()<BR>void flytTil(x,y)</P>
      </TD>
    </TR>
    <TR VALIGN=TOP>
      <TD>
        <P CLASS="western">Rektangel</P>
      </TD>
      <TD>
        <P CLASS="western">int x, y, dx, dy<BR>boolean udfyldt</P>
      </TD>
      <TD>
        <P CLASS="western">void tegn() <BR>void flytTil(x,y) <BR>double
        areal()</P>
      </TD>
    </TR>
    <TR VALIGN=TOP>
      <TD>
        <P CLASS="western">Trekant</P>
      </TD>
      <TD>
        <P CLASS="western">int x, y, dx, dy, dx2, dy2<BR>boolean udfyldt</P>
      </TD>
      <TD>
        <P CLASS="western">void tegn()<BR>void flytTil(x,y) <BR>double
        areal()</P>
      </TD>
    </TR>
  </TBODY>
</TABLE>
<P CLASS="western">Det er oplagt, at disse klasser har meget til
f&aelig;lles, og at nedarving b&oslash;r komme p&aring; tale. Men
hvordan skal arvehierakiet v&aelig;re?</P>
<H4 CLASS="western">Arvehierakiet i den koden&aelig;re, &quot;amerikanske&quot;
tankegang</H4>
<P CLASS="western">I den koden&aelig;re tankegang er sagen klar: 
</P>
<UL>
  <LI><P CLASS="western">Punkt er superklassen, 
  </P>
  <LI><P CLASS="western">Linje arver fra Punkt, tilf&oslash;jer to
  variabler og omdefinerer tegn(), 
  </P>
  <LI><P CLASS="western">Rektangel arver fra Linje og omdefinerer
  tegn(). 
  </P>
  <LI><P CLASS="western">Trekant kan arve fra Linje og genbruge tegn()
  til at tegne den f&oslash;rste streg (en anden mulighed var at arve
  fra Rektangel, s&aring; man f&aring;r variablen 'udfyldt' med).</P>
</UL>

<P CLASS="western" ALIGN=CENTER><IMG SRC="bog16_html_m7ce619ee.gif" NAME="Grafik37" ALIGN=BOTTOM BORDER=0></P>

<H4 CLASS="western" STYLE="">Arvehierakiet i
den analytiske, &quot;skandinaviske&quot; tankegang</H4>
<P CLASS="western">I den analytiske tankegang stiller sagen sig helt
anderledes: Linje kan ikke arve fra Punkt, da linjer ikke er punkter!</P>
<P CLASS="western">Faktisk er der ingen af de ovenfor n&aelig;vnte
klasser, der kan arve fra hinanden. Man m&aring; opfinde nogle
ekstra, mere abstrakte klasser som Figur og UdstraktFigur (en Figur
med et areal):</P>
<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0>
  <COL*>
  <COL*>
  <COL*>
  <THEAD>
    <TR VALIGN=TOP>
      <TH>
        <P CLASS="western">Klasse</P>
      </TH>
      <TH>
        <P CLASS="western">variabler</P>
      </TH>
      <TH>
        <P CLASS="western">metoder</P>
      </TH>
    </TR>
  </THEAD>
  <TBODY>
    <TR VALIGN=TOP>
      <TD>
        <P CLASS="western">Figur</P>
      </TD>
      <TD>
        <P CLASS="western">int x, y;</P>
      </TD>
      <TD>
        <P CLASS="western">void tegn();    (evt. abstrakt)<BR>void
        flytTil(x,y); 
        </P>
      </TD>
    </TR>
    <TR VALIGN=TOP>
      <TD>
        <P CLASS="western">UdstraktFigur</P>
      </TD>
      <TD>
        <P CLASS="western">int x, y;<BR>boolean udfyldt;</P>
      </TD>
      <TD>
        <P CLASS="western">void tegn();    (evt. abstrakt)<BR>void
        flytTil(x,y); <BR>double areal();  (evt. abstrakt)</P>
      </TD>
    </TR>
  </TBODY>
</TABLE>
<P CLASS="western">Nu kan Figur v&aelig;re superklassen, Punkt er-en
Figur og arver derfor fra Figur og definerer tegn(), UdstraktFigur
er-en Figur med en ekstra variabel og metode, Rektangel er-en
UdstraktFigur udvidet med variablerne dx og dy og ligeledes med
Trekant, der er-en UdstraktFigur udvidet med variablerne dx, dy, dx2
og dy2.</P>

<P CLASS="western" ALIGN=CENTER><IMG SRC="bog16_html_m4cdd68f6.gif" NAME="Grafik58" ALIGN=BOTTOM BORDER=0></P>


<H3 CLASS="western">15.1.3 <a name='afsn15.1.3'></a>&Oslash;velse</H3>
<OL>
  <LI><P CLASS="western">Kig p&aring; klassediagrammet for den
  koden&aelig;re tankegang. Hvor skulle cirkler placeres? ellipser?
  firkanter? polygoner? Tegn dem ind.</P>
  <LI><P CLASS="western">Kig p&aring; klassediagrammet for den
  analytiske tankegang. Hvor skulle cirkler placeres? ellipser?
  firkanter? polygoner? Tegn dem ind.</P>
  <LI><P CLASS="western">Hvordan adskiller diagrammerne sig? Hvilken
  tankegang kan du bedst lide? Hvorfor? Hvor er der mest kode? Hvilket
  klassediagram tror du er nemmest at udvide senere?</P>
</OL>

<H3 CLASS="western">15.1.4 <a name='afsn15.1.4'></a>Nedarvinger, hvor funktionaliteten ikke
udvides, men begr&aelig;nses</H3>
<P CLASS="western">Et dilemma i den analytiske tankegang er, hvad man
skal stille op, n&aring;r der konceptuelt er tale om en
specialisering (som alts&aring; burde medf&oslash;re arv), men hvor
funktionaliteten <I>begr&aelig;nses</I> i stedet for (som normalt) at
blive udvidet.</P>
<P CLASS="western">T&aelig;nk f.eks. p&aring; cirkler og ellipser.
Det er klart, at Ellipse skal have to variabler til at angive radius
(h&oslash;jde og bredde), mens Cirkel kun har brug for &eacute;n
radius. 
</P>
<P CLASS="western">P&aring; den anden side er der ingen tvivl om, at
en cirkel er en slags ellipse (en hel rund ellipse), s&aring;
konceptuelt g&aelig;lder relationen Cirkel 'er-en' Ellipse, selvom
Ellipse-klassen har flere data end Cirkel.</P>

<H2 CLASS="western" STYLE="">15.2 <a name='afsn15.2'></a><SPAN LANG="da-DK">Delegering
(i stedet for arv)</SPAN></SPAN></H2>
<BLOCKQUOTE CLASS="definition-western">Delegering: At et objekt har
et andet objekt, som det 'uddelegerer' nogle opgaver til</BLOCKQUOTE>
<P CLASS="western">Ofte har man brug for at udvide og genbruge en
klasses funktionalitet. Den s&aelig;dvanlige m&aring;de at g&oslash;re
det p&aring; er, som bekendt, ved at lave en nedarving, men det kan
v&aelig;re, at det (af den ene eller anden grund) er mere
hensigtsm&aelig;ssigt at bruge delegering i stedet.</P>
<P CLASS="western">Delegering g&aring;r ud p&aring; at skrive klassen
med ekstra funktionalitet, s&aring;dan at den <I>bruger</I> den
oprindelige klasse i stedet for at arve fra den.</P>
<H3 CLASS="western">15.2.1 <a name='afsn15.2.1'></a>At skjule nogle metoder</H3>
<P CLASS="western">Eksempelvis kan det v&aelig;re, man &oslash;nsker
at 'arve' en klasses data, og nogle men ikke alle, dens metoder. S&aring;
vil delegering sandsynligvis v&aelig;re mere hensigtsm&aelig;ssigt
end nedarving.</P>
<IMG SRC="bog16_html_2831ed9a.gif" NAME="Grafik66" ALIGN=RIGHT BORDER=0>
<BLOCKQUOTE CLASS="definition-western">Arv kan ikke skjule metoder,
men det kan delegering</BLOCKQUOTE>
<P CLASS="western">Man vil lave datastrukturen 'stak', som er en
liste, hvor man kun kan tilf&oslash;je og fjerne elementer fra den
ene ende (l&aelig;gge p&aring; og tage af stakken). Man <I>kunne</I>
arve fra Vector:</P>
<PRE CLASS="kode-western">public class StakMedNedarving <B>extends java.util.Vector</B>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public void l&aelig;gP&aring;(Object o)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    addElement(o);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public Object tagAf()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Object o = lastElement();</SPAN>
<SPAN LANG="da-DK">    setSize( size() - 1 );</SPAN>
<SPAN LANG="da-DK">    return o;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
... men hvordan kan man nu v&aelig;re sikker p&aring;, at de, der
bruger StakMedNedarving, bruger de nye metoder? 
</P>
<P CLASS="western">De kunne godt kalde elementAt() eller nogen af de
andre metoder som StakMedNedarving arver fra Vector, og der er ikke
nogen elegant m&aring;de at forhindre det p&aring;.</P>
<P CLASS="western">Det er mere hensigtsm&aelig;ssigt at <SPAN STYLE="font-weight: medium"><I>delegere
</I></SPAN>opgaven med at holde styr p&aring; listen til Vector i
stedet for at arve fra Vector:</P>
<PRE CLASS="kode-western">public class StakMedDelegering
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK"><B>  private java.util.Vector v = new java.util.Vector();</B></SPAN><IMG SRC="bog16_html_40862f89.gif" NAME="Grafik59" ALIGN=RIGHT BORDER=0>

<SPAN LANG="da-DK">  public void l&aelig;gP&aring;(Object o)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    <B>v.</B>addElement(o);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public Object tagAf()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Object o = <B>v.</B>lastElement();</SPAN>
<SPAN LANG="da-DK">    <B>v.</B>setSize( <B>v.</B>size() - 1 );</SPAN>
<SPAN LANG="da-DK">    return o;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<P CLASS="western" STYLE="">Nu er vektoren
indkapslet i stakken, og det er umuligt at kalde andre metoder end
dem, der er defineret i StakMedDelegering. 
</P>
<P CLASS="western">Det er sj&aelig;ldent en god id&eacute; at arve
fra 'v&aelig;rkt&oslash;jsklasser' s&aring;som Vector: Man har nemlig
ikke mulighed for at forhindre brugeren af den nye klasse i at kalde
nogle metoder, det ikke var meningen, han skulle kalde.</P>
<P CLASS="western">StakMedNedarving er et eksempel p&aring; den
'koden&aelig;re' tankegang beskrevet i <a href='kapitel15.jsp#afsn15.1.1'>afsnit 15.1.1</a> og illustrerer
et af problemerne med denne m&aring;de at t&aelig;nke p&aring;.</P>
<P CLASS="western">I C++ kan problemet med at skjule superklassens
metoder l&oslash;ses ved at bruge s&aring;kaldt &quot;privat
nedarving&quot;, hvor kun underklassen har adgang til de nedarvede
metoder (s&aring; det virker, som om metoderne er erkl&aelig;ret
private i den nedarvende klasse).</P>
<H4 CLASS="western">Forhindre metodekald ved at kaste undtagelser</H4>
<P CLASS="western">En anden mulighed kunne v&aelig;re at tilsides&aelig;tte
alle de nedarvede metoder, der var u&oslash;nskede, med nogle nye,
der konsekvent kaster en undtagelse (eng.: exception), hvis de bliver
kaldt. Dette er naturligvis ikke specielt elegant, men fra tid til
anden kan man blive tvunget ud i den l&oslash;sning (et andet
eksempel ses i <a href='kapitel17.jsp#afsn17.1.3'>afsnit 17.1.3</a>, G&oslash;re data uforanderlige vha. Proxy).
</P>
<PRE CLASS="kode-western">public class StakMedNedarvingKastUndtagelser extends java.util.Vector
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public void l&aelig;gP&aring;(Object o)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    super.addElement(o);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public Object tagAf()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Object o = lastElement();</SPAN>
<SPAN LANG="da-DK">    setSize( size() - 1 );</SPAN>
<SPAN LANG="da-DK">    return o;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK"><B>  public void addElement(<FONT SIZE=1 STYLE="font-size: 8pt">Object obj</FONT>) {</B></SPAN>
<SPAN LANG="da-DK"><B>    throw new UnsupportedOperationException(&quot;Ikke tilladt p&aring; en stak&quot;);</B></SPAN>
<SPAN LANG="da-DK"><B>  }</B></SPAN>

<SPAN LANG="da-DK"><B>  public void setSize(int newSize)   {</B></SPAN>
<SPAN LANG="da-DK"><B>    throw new UnsupportedOperationException(&quot;Ikke tilladt p&aring; en stak&quot;);</B></SPAN>
<SPAN LANG="da-DK"><B>  }</B></SPAN>
<SPAN LANG="da-DK"><B>  </B></SPAN>
<SPAN LANG="da-DK"><B>  public Object elementAt(int index) {</B></SPAN>
<SPAN LANG="da-DK"><B>    throw new UnsupportedOperationException(&quot;Ikke tilladt p&aring; en stak&quot;);</B></SPAN>
<SPAN LANG="da-DK"><B>  }</B></SPAN>

<SPAN LANG="da-DK"><B>  pub<FONT SIZE=1 STYLE="font-size: 8pt">lic void setElementAt(Object obj, int index) {</FONT></B></SPAN>
<SPAN LANG="da-DK"><B>    throw new UnsupportedOperationException(&quot;Ikke tilladt p&aring; en stak&quot;);</B></SPAN>
<SPAN LANG="da-DK"><B>  }</B></SPAN>

<SPAN LANG="da-DK"><B>  public void insertElementAt(Object obj, int index) {</B></SPAN>
<SPAN LANG="da-DK"><B>    throw new UnsupportedOperationException(&quot;Ikke tilladt p&aring; en stak&quot;);</B></SPAN>
<SPAN LANG="da-DK"><B>  }</B></SPAN>
<SPAN LANG="da-DK"><I>  // osv...</I></SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
En stor ulempe ved denne teknik er, at fejl f&oslash;rst fanges p&aring;
k&oslash;rselstidspunktet i stedet for under overs&aelig;ttertidspunktet.
</P>
<P CLASS="western">En anden ulempe er, at hver gang superklassen f&aring;r
defineret en ny metode, der ikke skal kunne kaldes i nedarvingen,
skal man huske at opdatere nedarvingen tilsvarende. Vector er s&aring;ledes
blevet udvidet med et antal metoder fra JDK1.1 til JDK1.2 (f.eks.
get(), add() og de andre metoder i interfacet List - se <a href='kapitel1.jsp'>kapitel 1</a>,
Samlinger af data), og koden ovenfor skulle derfor udvides med disse
metoder, da man skiftede til JDK1.2 (i &oslash;vrigt er de fleste af
Vectors metoder erkl&aelig;ret final og kan derfor faktisk
overhovedet ikke tilsides&aelig;ttes i en nedarving).</P>
<H3 CLASS="western">15.2.2 <a name='afsn15.2.2'></a>Modellering af roller</H3>
<P CLASS="western">Et andet tilf&aelig;lde, hvor delegering er en
bedre id&eacute; end arv, er, hvor objekterne kan have flere roller
eller skifte rolle under udf&oslash;relsen af programmet.</P>
<BLOCKQUOTE CLASS="definition-western">Arv er kun velegnet til
&quot;er-en&quot;-relationer, der aldrig &aelig;ndrer sig under
k&oslash;rslen</BLOCKQUOTE>
<P CLASS="western">Lad os se p&aring; et eksempel inden for en
virksomhed. Her er personer, der kan v&aelig;re ledere, ansatte og
konsulenter (man kunne f.eks. forestille sig, at de har hver sin
l&oslash;nberegnings-metode, forskellige bef&oslash;jelser, osv.
...). 
</P>
<P CLASS="western">Man kunne modellere rollerne med nedarving som
vist i figuren herunder:</P>
<P CLASS="western" ALIGN=CENTER><IMG SRC="bog16_html_m331d71b9.gif" NAME="Grafik60" ALIGN=BOTTOM BORDER=0></P>
<P ALIGN=CENTER STYLE="margin-top: 0.11cm; margin-bottom: 0.11cm"><FONT SIZE=2 STYLE="font-size: 9pt"><I>Rollerne
modelleret med nedarving</I></FONT></P>
<P CLASS="western">Der er en f&aelig;lles superklasse...</P>
<PRE CLASS="kode-western">public class Person
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  String fornavn;</SPAN>
<SPAN LANG="da-DK">  String efternavn;</SPAN>
<SPAN LANG="da-DK">  String cpr;</SPAN>

<SPAN LANG="da-DK">  public String hentFornavn() { return cpr; }</SPAN>

<SPAN LANG="da-DK">  <I>// flere metoder og variabler...</I></SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
... og nogle nedarvinger af Person, bl.a. lederen:</P>
<PRE CLASS="kode-western">public class LederArv <B>extends Person</B>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  java.util.List ansatte;</SPAN>

<SPAN LANG="da-DK">  <I>// opret en leder</I></SPAN>
<SPAN LANG="da-DK">  public LederArv() { }</SPAN>

<SPAN LANG="da-DK">  <I>// opret en leder-rolle med en eksisteren person (ikke s&aring; elegant...)</I></SPAN>
<SPAN LANG="da-DK">  public LederArv(Person p)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    this.fornavn   = p.fornavn;</SPAN>
<SPAN LANG="da-DK">    this.efternavn = p.efternavn;</SPAN>
<SPAN LANG="da-DK">    this.cpr       = p.cpr;</SPAN>
<SPAN LANG="da-DK">    <I>// kopi&eacute;r resten af Persons variabler her...</I></SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public java.util.List hentAnsatte() { return ansatte; }</SPAN>

<SPAN LANG="da-DK">  <I>// flere metoder og variabler...</I></SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
Problemerne med id&eacute;en om at bruge nedarving kan v&aelig;re at:</P>
<OL>
  <LI><P CLASS="western">Personer kan i virkeligheden udfylde flere
  roller samtidigt. 
  </P>
  <LI><P CLASS="western">Personer kan i virkeligheden skifte rolle. 
  </P>
</OL>

<H4 CLASS="western">Hvis objektet kan udfylde flere roller</H4>
<P CLASS="western">Hvis kombinationer af rollerne kan opst&aring;,
s&aring;dan at f.eks. en person samtidig er konsulent
(afl&oslash;nningsm&aelig;ssigt) og leder (m.h.t. Bef&oslash;jelser),
vil ingen af klasserne passe.</P>
<P CLASS="western">Skulle rollerne alligevel modelleres med roller,
ville man blive n&oslash;dsaget til at lave nye nedarvinger for
kombinationsrollerne, f.eks. LederOgKonsulent og AnsatOgKonsulent.</P>
<H4 CLASS="western">Hvis objektet kan skifte rolle</H4>
<P CLASS="western">V&aelig;rre ser det ud, hvis objektet kan skifte
rolle (f.eks. fra Ansat til Leder). Da man ikke kan lave om p&aring;
et objekts type (klasse), n&aring;r det f&oslash;rst er oprettet, er
der intet at g&oslash;re andet end at oprette et objekt med den nye
rolle og kopiere alle f&aelig;lles data (dem, der stammer fra
Person-klassen) fra det oprindelige objekt til det nye.</P>
<P CLASS="western">Skal vi lave en Ansat om til en Leder, kan det
alts&aring; kun ske ved at oprette en ny Leder og smide det gamle
Ansat-objekt v&aelig;k. Vi m&aring; s&aring; kode Leder's konstrukt&oslash;r
til at kopiere de f&aelig;lles data (og i &oslash;vrigt h&aring;be
p&aring;, at der ikke er en anden del af programmet, der &aelig;ndrer
i data, efter at vi har kopieret dem).</P>
<H4 CLASS="western">Situationen med delegering i stedet for arv</H4>
<P CLASS="western">I stedet for arv kunne vi modellere rollerne med
delegering som vist nedenfor. Nu har Leder, Ansat og Konsulent en
reference til et Person-objekt, og alle metodekald, der har med
personen at g&oslash;re, delegeres videre til Person-objektet.</P>
<P CLASS="western" ALIGN=CENTER><IMG SRC="bog16_html_72ad5abd.gif" NAME="Grafik61" ALIGN=BOTTOM BORDER=0></P>
<P ALIGN=CENTER STYLE="margin-top: 0.11cm; margin-bottom: 0.11cm"><FONT SIZE=2 STYLE="font-size: 9pt"><I>Rollerne
modelleret med delegering</I></FONT></P>
<PRE CLASS="kode-western">public class LederDelegering
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK"><B>  private Person person;</B></SPAN>
<SPAN LANG="da-DK">  private java.util.List ansatte;</SPAN>

<SPAN LANG="da-DK">  <I>// opret en leder</I></SPAN>
<SPAN LANG="da-DK">  public LederDelegering()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    person = new Person();</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  <I>// opret en leder-rolle med en eksisteren person (mere elegant)</I></SPAN>
<SPAN LANG="da-DK">  public LederDelegering(Person p)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    person = p;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public String hentFornavn() { return person.hentFornavn(); } <I>// deleg&eacute;r</I></SPAN>

<SPAN LANG="da-DK">  public java.util.List hentAnsatte() { return ansatte; }</SPAN>

<SPAN LANG="da-DK">  <I>// flere metoder og variabler...</I></SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
Det er let at lade en Person have flere roller samtidig: S&aring;
deles et Leder-objekt og et Konsulent-objekt om et f&aelig;lles
Person-objekt.</P>
<P CLASS="western">Det er ogs&aring; let at lade en Person skifte
rolle: Skal vi lave en Ansat om til en Leder, kan det ske ved at
oprette en ny Leder og l&aelig;gge det eksisterende Person-objekt ind
i det.</P>
<P CLASS="western">Bem&aelig;rk, at Leder, Ansat og Konsulent nu ikke
mere er af typen Person. Dette er ikke noget problem, hvis man (som
eksemplet foruds&aelig;tter) har separate lister af ledere, ansatte
og konsulenter. Har man brug for en f&aelig;lles superklasse, kunne
man definere et interface (eller en abstrakt klasse) PersonIF, som de
alle implementerede, og som havde de metoder der var f&aelig;lles for
ledere, ansatte og konsulenter.</P>
<H3 CLASS="western">15.2.3 <a name='afsn15.2.3'></a>Resum&eacute; og konklusion</H3>

	    Dette afsnit er ikke omfattet af Åben Dokumentslicens.<br>
	    Du skal <a href="/index_VP.html#bestil">købe</a> bogen for at
	    måtte læse dette afsnit.

  <form action="http://javabog.dk/VP/kapitel15.jsp#afsn15.2.3">
  <input type='checkbox' name='vis' value='15.2.3'>Jeg erklærer, at jeg allerede har købt bogen<br />
  <input type='checkbox' name='vis' value='15.2.3'>Jeg lover at anskaffe den i nær fremtid.<br />
  <input type='submit' value='Vis mig dette afsnit'>
  </form>

	  <H2 CLASS="western">15.3 <a name='afsn15.3'></a>Specific&eacute;r funktionalitet i et
interface</SPAN></H2>

	    Dette afsnit er ikke omfattet af Åben Dokumentslicens.<br>
	    Du skal <a href="/index_VP.html#bestil">købe</a> bogen for at
	    måtte læse dette afsnit.

  <form action="http://javabog.dk/VP/kapitel15.jsp#afsn15.3">
  <input type='checkbox' name='vis' value='15.3'>Jeg erklærer, at jeg allerede har købt bogen<br />
  <input type='checkbox' name='vis' value='15.3'>Jeg lover at anskaffe den i nær fremtid.<br />
  <input type='submit' value='Vis mig dette afsnit'>
  </form>

	  
<H3 CLASS="western">15.3.1 <a name='afsn15.3.1'></a>Repetition af interfaces</H3>
<P CLASS="western">I generel sprogbrug er et interface (da.:
snitflade) en form for gr&aelig;nseflade, som man g&oslash;r noget
gennem. F.eks. er en grafisk brugergr&aelig;nseflade de vinduer med
knapper, indtastningsfelter og kontroller, som brugeren har til
interaktion med programmet.</P>

<P CLASS="western" STYLE="">Vi minder om, at
en klasse er definitionen af en type objekter. Her kunne man opdele i</P>
<OL>
  <LI><P CLASS="western"><I>Gr&aelig;nsefladen</I> - hvordan
  objekterne kan bruges udefra.<BR>Dette udg&oslash;res af navnene<A CLASS="sdfootnoteanc" NAME="sdfootnote3anc" HREF="#sdfootnote3sym"><SUP>3</SUP></A>
  p&aring; metoderne, der kan ses udefra.</P>
  <LI><P CLASS="western"><I>Implementationen</I> - hvordan objekterne
  virker indeni.<BR>Dette udg&oslash;res af variabler og programkoden
  i metodekroppene.</P>
</OL>
<P CLASS="western">Et 'interface' svarer til punkt 1): En definition
af, hvordan objekter bruges udefra. Man kan sige, at et interface er
en &quot;halv&quot; klasse.</P>
<BLOCKQUOTE CLASS="definition-western">Et interface er en samling
navne p&aring; metoder (uden krop)</BLOCKQUOTE>
<P CLASS="western">Et interface kan implementeres af en klasse - det
vil sige, at klassen definerer alle interfacets metoder sammen
med programkoden, der beskriver, hvad der skal ske, n&aring;r
metoderne kaldes.</P>
<H3 CLASS="western">15.3.2 <a name='afsn15.3.2'></a>Eksempel: Stak</H3>
<P CLASS="western">Gr&aelig;nsefladen til stakken (beskrevet i <a href='kapitel15.jsp#afsn15.2'>afsnit
15.2</a>) kunne v&aelig;re defineret i et interface:</P>
<PRE CLASS="kode-western">public interface Stak
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public void l&aelig;gP&aring;(Object o);</SPAN>
<SPAN LANG="da-DK">  public Object tagAf();</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<P CLASS="western">Der kan v&aelig;re mange klasser, der
implementerer Stak, f.eks. de to fra forrige afsnit:</P>
<PRE CLASS="kode-western">public class StakMedNedarving2 extends java.util.Vector <B>implements Stak</B>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public void l&aelig;gP&aring;(Object o)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    addElement(o);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public Object tagAf()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Object o = lastElement();</SPAN>
<SPAN LANG="da-DK">    setSize( size() - 1 );</SPAN>
<SPAN LANG="da-DK">    return o;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
og:</P>
<PRE CLASS="kode-western">public class StakMedDelegering2 <B>implements Stak</B>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  private java.util.Vector v = new java.util.Vector();</SPAN>

<SPAN LANG="da-DK">  public void l&aelig;gP&aring;(Object o)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    v.addElement(o);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public Object tagAf()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Object o = v.lastElement();</SPAN>
<SPAN LANG="da-DK">    v.setSize( v.size() - 1 );</SPAN>
<SPAN LANG="da-DK">    return o;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<P CLASS="western">Et enkelt sted i programmet er det n&oslash;dvendigt
at beslutte, hvilken implementation af Stak der anvendes, nemlig n&aring;r
objektet oprettes:</P>
<PRE CLASS="kode-western">  Stak s = new StakMedNedarving2();</PRE><P CLASS="western">
<SPAN LANG="da-DK">Resten af programmet arbejder bare med objekter af
typen Stak <I>uden</I> at vide noget om, hvordan de er implementeret,
f.eks.:</SPAN></P>
<PRE CLASS="kode-western">  ...
<SPAN LANG="da-DK">  System.out.print( s.tagAf() );</SPAN>
<SPAN LANG="da-DK">  System.out.print( s.tagAf() );</SPAN>
<SPAN LANG="da-DK">  fyldStakkenOp(s);</SPAN>
<SPAN LANG="da-DK">  ...</SPAN></PRE><P CLASS="western" STYLE="margin-top: 0cm; margin-bottom: 0cm">
Ogs&aring; metoder, f.eks. fyldStakkenOp(), kan arbejde p&aring;
ethvert objekt, der implementerer Stak-interfacet:</P>
<PRE CLASS="kode-western">  public void fyldStakkenOp(Stak s)
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    s.l&aelig;gP&aring;(&quot;Hej&quot;);</SPAN>
<SPAN LANG="da-DK">    s.l&aelig;gP&aring;(&quot;med&quot;);</SPAN>
<SPAN LANG="da-DK">    s.l&aelig;gP&aring;(&quot;dig&quot;);</SPAN>
<SPAN LANG="da-DK">  }</SPAN></PRE>
<P CLASS="western">Her er et klassediagram, der illustrerer, hvordan
en klient (en klasse eller et program) benytter noget funktionalitet
beskrevet i Stak. Metoder er ikke vist i diagrammet.</P>
<P CLASS="western" ALIGN=CENTER><IMG SRC="bog16_html_m5b99b012.gif" NAME="Grafik62" ALIGN=BOTTOM BORDER=0></P>
<P CLASS="western">Pilen fra Klient til Stak viser, at klienten har
en instans af Stak (en variabel af type Stak, der jo kan pege p&aring;
alle objekter, der implementerer Stak-interfacet). 
</P>
<P CLASS="western">Stakimpl1 og Stakimpl2 er to klasser, der
implementerer Stak-interfacet<A CLASS="sdfootnoteanc" NAME="sdfootnote4anc" HREF="#sdfootnote4sym"><SUP>4</SUP></A>
(nedarvingspilen er tegnet med stiplet linje for at markere, at der
er tale om implementation af interface, ikke nedarving), f.eks.:
StakMedNedarving og StakMedDelegering.</P>
<H3 CLASS="western">15.3.3 <a name='afsn15.3.3'></a>Eksempel: Collections-klasserne</H3>
<P CLASS="western">Funktionaliteten i datastrukturerne i
Collections-klasserne er alle specificerede i interfaces, og brugeren
opfordres til at henvise s&aring; lidt til implementationerne (som
f.eks. ArrayList og LinkedList) som muligt og s&aring; meget til
interfacene (som f.eks. List) som muligt:</P>
<PRE CLASS="kode-western">  List l = new ArrayList();
<SPAN LANG="da-DK">  </SPAN>
<SPAN LANG="da-DK"><I>  // ... resten af programmet arbejder bare med en List-variabel</I></SPAN>
<SPAN LANG="da-DK"><I>  //     uden at kende til den konkrete implementation af listen</I></SPAN></PRE><P CLASS="western">
Det g&oslash;r det lettere senere at udskifte implementationen af
datastrukturen med en anden med samme funktionalitet, men anderledes
indre struktur, f.eks. udskifte ArrayList med LinkedList:</P>
<PRE CLASS="kode-western">  List l = new LinkedList();
<SPAN LANG="da-DK">  </SPAN>
<SPAN LANG="da-DK"><I>  // ... resten af programmet arbejder bare med en List-variabel</I></SPAN>
<SPAN LANG="da-DK"><I>  //     uden at kende til den konkrete implementation af listen</I></SPAN></PRE><P CLASS="western">
Se ogs&aring; <a href='kapitel1.jsp#afsn1.1.2'>afsnit 1.1.2</a>, Interfacene til lister og m&aelig;ngder.</P>
<H2 CLASS="western">15.4 <a name='afsn15.4'></a>Konstanterkl&aelig;ringer i et interface</SPAN></H2>
<P CLASS="western">Det f&oslash;lgende er et lille fif i Java, der
kan g&oslash;re programkoden mere l&aelig;selig (i C++ har man
mulighed for at erkl&aelig;re globale konstanter, s&aring; her er
fiffet ikke relevant): 
</P>
<P CLASS="western">Ved at erkl&aelig;re konstanter, der skal bruges
fra flere klasser i et interface, kan klasser, der har brug for disse
konstanter, implementere interfacet og derefter bruge konstanterne
<I>uden</I> at skulle skrive et klassenavn foran.</P>
<P CLASS="western">Eksempelvis kunne vi definere et interface med
nogle tilstande:</P>
<PRE CLASS="kode-western">public interface Tilstandsliste
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  int IKKE_STARTET = 0;</SPAN>
<SPAN LANG="da-DK">  int STARTER = 1;</SPAN>
<SPAN LANG="da-DK">  int I_GANG = 2;</SPAN>
<SPAN LANG="da-DK">  int STOPPER = 3;</SPAN>
<SPAN LANG="da-DK">  int STOPPET = 4;</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
Bem&aelig;rk, at variabler i et interface automatisk erkl&aelig;res
public static final (klassevariabel, der kan afl&aelig;ses af alle,
men ikke &aelig;ndres).</P>
<P CLASS="western">Nu kunne vi selvf&oslash;lgelig bruge
konstanterne, som man plejer, ved at skrive klassen foran:</P>
<PRE CLASS="kode-western">public class BenytTilstande1
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public static void main(String[] args)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    int tilstand = <B>Tilstandsliste.IKKE_STARTET</B>;</SPAN>

<SPAN LANG="da-DK">    while (tilstand != <B>Tilstandsliste.STOPPET</B>) {</SPAN>
<SPAN LANG="da-DK">      System.out.println(&quot;tilstand = &quot;+tilstand);</SPAN>
<SPAN LANG="da-DK">      tilstand++;</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
... men i klasser, der implementerer Tilstandsliste, kan det skrives
kortere:</P>
<PRE CLASS="kode-western">public class BenytTilstande2 <B>implements Tilstandsliste</B>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public static void main(String[] args)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    int tilstand = <B>IKKE_STARTET</B>;</SPAN>
<SPAN LANG="da-DK">    </SPAN>
<SPAN LANG="da-DK">    while (tilstand != <B>STOPPET</B>) {</SPAN>
<SPAN LANG="da-DK">      System.out.println(&quot;tilstand = &quot;+tilstand);</SPAN>
<SPAN LANG="da-DK">      tilstand++;</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<H2 CLASS="western">15.5 <a name='afsn15.5'></a>Markeringsinterface</SPAN></H2>
<P CLASS="western">Det f&oslash;lgende bliver brugt en del i Javas
standardbibliotek og er derfor v&aelig;rd at n&aelig;vne (de
defineres sj&aelig;ldent uden for standardbiblioteket).</P>
<BLOCKQUOTE CLASS="definition-western">Et markeringsinterface
erkl&aelig;rer ingen metoder, men markerer et eller andet. <BR>En
klasse m&aelig;rkes ved at implementere markeringsinterfacet.</BLOCKQUOTE>
<P CLASS="western">Et markeringsinterface (eng.: marker interface) er
et interface uden nogen metoder (eller variabler). Det tjener kun til
at m&aelig;rke klasser, s&aring;dan at deres objekter kan genkendes
og behandles s&aelig;rskilt af et eller andet system.</P>
<P CLASS="western">Vigtigste eksempel fra standardbiblioteket p&aring;
et markeringsinterface er Serializable, der tjener til at markere, om
en klasse m&aring; serialiseres.</P>
<P CLASS="western">Et andet er Cloneable (der markerer, om det er
lovligt at kopiere et objekt ved at kalde dets clone()-metode).</P>
<P CLASS="western">Et tredje er Remote i pakken java.rmi, der
markerer, om et objekt er et 'fjernobjekt' i RMI (og dermed, om det
skal forblive p&aring; serveren, og klienten skal have en
fjernreference til det, eller det skal serialiseres, og indholdet
transporteres over til klienten, som da f&aring;r en kopi af
objektet).</P>

<H2 CLASS="western">15.6 <a name='afsn15.6'></a>Ansvarsomr&aring;der</SPAN></H2>
<P CLASS="western">En grundid&eacute; inden for objektorienteret
design er, at hvert objekt skal have et eller flere ansvarsomr&aring;der.</P>
<P CLASS="western">Ansvarsomr&aring;der for et objekt kan v&aelig;re:</P>
<UL>
  <LI><P CLASS="western">At oprette nye objekter eller udf&oslash;re
  en beregning</P>
  <LI><P CLASS="western">At foretage en handling i andre objekter</P>
  <LI><P CLASS="western">At kontrollere og koordinere aktiviteter i
  andre objekter</P>
  <LI><P CLASS="western">At kende private data</P>
  <LI><P CLASS="western">At kende relaterede objekter</P>
  <LI><P CLASS="western">At kende ting, som objektet kan beregne</P>
</UL>
<H3 CLASS="western">15.6.1 <a name='afsn15.6.1'></a>Eksempel p&aring; tildeling af
ansvarsomr&aring;der</H3>
<P CLASS="western"><SPAN LANG="da-DK">Et eksempel p&aring;, hvordan
man tildeler objekter ansvarsomr&aring;der, er vist i neden for (fra
bogen 'Objektorienteret programmering i Java', </SPAN><SPAN STYLE="font-weight: medium"><A CLASS="western" HREF="http://javabog.dk/"><SPAN LANG="da-DK">http://javabog.dk</SPAN></A></SPAN><SPAN LANG="da-DK">,
<a href='kapitel4.jsp'>kapitel 4</a>):</SPAN></P>
<PRE CLASS="kode-western">public class Terning
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public int v&aelig;rdi;</SPAN>

<SPAN LANG="da-DK">  public Terning()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    kast();</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public void kast()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    double tilf&aelig;ldigtTal = Math.random();</SPAN>
<SPAN LANG="da-DK">    v&aelig;rdi = (int) (tilf&aelig;ldigtTal * 6 + 1);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public String toString()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    String svar = &quot;&quot;+v&aelig;rdi;</SPAN>
<SPAN LANG="da-DK">    return svar;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
Et terning-objekt har ansvaret for det, som vedr&oslash;rer den
enkelte terning, dvs. ansvar for at vise den enkelte ternings v&aelig;rdi
og at kaste den enkelte terning.</P>
<P CLASS="western">Et rafleb&aelig;ger-objekt har ansvar for alt det,
som vedr&oslash;rer alle terningerne, dvs. oprettelsen af
terningerne, kaste terningerne, kende summen af deres v&aelig;rdier
og beskrive b&aelig;gerets indhold.</P>

<P CLASS="western" STYLE="">Man kunne godt
n&oslash;jes med &eacute;n klasse og s&aring; have al koden i den,
men en opdeling i forskellige klasser og dermed objekter med hvert
sit ansvarsomr&aring;de g&oslash;r programmet lettere at overskue.</P>
<PRE CLASS="kode-western">import java.util.*;

<SPAN LANG="da-DK">public class Raflebaeger</SPAN>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public Vector terninger;            <I>// Raflebaeger har en liste af terninger</I></SPAN>

<SPAN LANG="da-DK">  public Raflebaeger(int antalTerninger)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    terninger = new Vector();</SPAN>
<SPAN LANG="da-DK">    for (int i=0;i&lt;antalTerninger;i++)</SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      Terning t;</SPAN>
<SPAN LANG="da-DK">      t = new Terning();</SPAN>
<SPAN LANG="da-DK">      tilf&oslash;j(t);</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public void tilf&oslash;j(Terning t)       <I>// L&aelig;g en terning i b&aelig;geret</I></SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    terninger.addElement(t);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public void ryst()                <I>// Kast alle terningerne</I></SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    for (int i=0;i&lt;terninger.size();i++) </SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      Terning t;</SPAN>
<SPAN LANG="da-DK">      t = (Terning) terninger.elementAt(i);</SPAN>
<SPAN LANG="da-DK">      t.kast();</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public int sum()                      <I>// Summen af alle terningers v&aelig;rdier</I></SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    int resultat;</SPAN>
<SPAN LANG="da-DK">    resultat=0;</SPAN>
<SPAN LANG="da-DK">    for (int i=0;i&lt;terninger.size();i++) </SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      Terning t;</SPAN>
<SPAN LANG="da-DK">      t = (Terning) terninger.elementAt(i);</SPAN>
<SPAN LANG="da-DK">      resultat = resultat + t.v&aelig;rdi;</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">    return resultat;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">  </SPAN>
<SPAN LANG="da-DK">  public int antalDerViser(int v&aelig;rdi) <I>// Antal terninger med en bestemt v&aelig;rdi</I></SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    int resultat;</SPAN>
<SPAN LANG="da-DK">    resultat = 0;</SPAN>
<SPAN LANG="da-DK">    for (int i=0;i&lt;terninger.size();i++) </SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      Terning t;</SPAN>
<SPAN LANG="da-DK">      t = (Terning) terninger.elementAt(i);</SPAN>
<SPAN LANG="da-DK">      if (t.v&aelig;rdi==v&aelig;rdi) </SPAN>
<SPAN LANG="da-DK">      {</SPAN>
<SPAN LANG="da-DK">        resultat = resultat + 1;</SPAN>
<SPAN LANG="da-DK">      }</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">    return resultat;</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public String toString ()           <I>// Beskriv b&aelig;gerets indhold</I></SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    // (vektorens toString() kalder toString() p&aring; hver terning)</SPAN>
<SPAN LANG="da-DK">    return terninger.toString();</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<H3 CLASS="western">15.6.2 <a name='afsn15.6.2'></a>Ekspert</H3>
<BLOCKQUOTE CLASS="definition-western">Hvilke ansvarsomr&aring;der
skal de enkelte klasser have?</BLOCKQUOTE>
<P CLASS="western">Tildel den klasse, der har den n&oslash;dvendige
information til at udf&oslash;re handlingen, ansvaret for handlingen.</P>
<P CLASS="western">I rafleb&aelig;ger-eksemplet har
Terning-objekterne ansvar for de ting, der har med den enkelte
terning at g&oslash;re, og Rafleb&aelig;geret har ansvar for de ting,
der vedr&oslash;rer alle terningerne, da b&aelig;geret kender
terningerne.</P>
<H3 CLASS="western">15.6.3 <a name='afsn15.6.3'></a>Skaber</H3>
<BLOCKQUOTE CLASS="definition-western">Hvem skal v&aelig;re ansvarlig
for at oprette nye instanser (objekter) af en given klasse?</BLOCKQUOTE>
<P CLASS="western">En klasse A skal v&aelig;re ansvarlig for at
oprette nye instanser af en anden klasse B, hvis en eller flere af de
f&oslash;lgende ting g&aelig;lder:</P>
<UL>
  <LI><P CLASS="western">A indeholder objekter af typen B</P>
  <LI><P CLASS="western">A best&aring;r af objekter af typen B</P>
  <LI><P CLASS="western">A kender de data, som B skal initialiseres
  med</P>
  <LI><P CLASS="western">A bruger objekter af typen B meget</P>
</UL>
<P CLASS="western">I rafleb&aelig;ger-eksemplet skal et objekt af
typen Raflebaeger v&aelig;re ansvarlig for at oprette
Terning-objekterne, da et rafleb&aelig;ger indeholder terninger, og
rafleb&aelig;geret bruger Terning-objekterne meget.</P>
<P CLASS="western"><a href='kapitel16.jsp'>Kapitel 16</a>, Skabende designm&oslash;nstre, handler
i &oslash;vrigt om oprettelse af objekter.</P>
<H2 CLASS="western" STYLE="">15.7 <a name='afsn15.7'></a>Lav kobling
og h&oslash;j koh&aelig;sion</SPAN></H2>
<P CLASS="western">N&aring;r man designer sit program, m&aring; man
g&oslash;re sig klart, hvilke dele af programmet der vil v&aelig;re
hyppige udvidelser og omstruktureringer i fremtiden. 
</P>
<P CLASS="western">Disse dele skal gerne v&aelig;re kendetegnet af
lav kobling udadtil og h&oslash;j koh&aelig;sion indadtil.</P>
<H3 CLASS="western">15.7.1 <a name='afsn15.7.1'></a>Lav kobling</H3>
<BLOCKQUOTE CLASS="definition-western">Hvordan opn&aring;s det, at
klasserne i et program bliver lette at udskifte, og eventuelt
genbruge?</BLOCKQUOTE>
<P CLASS="western">Koblingen (bindingen) mellem klasser er et m&aring;l
for, hvor afh&aelig;ngige klasserne er af hinanden. Programmer med
h&oslash;j kobling er kendetegnet ved, at &aelig;ndringer i en klasse
har stor indflydelse p&aring; de &oslash;vrige dele af programmet, og
at koden i den enkelte klasse er sv&aelig;r at forst&aring; isoleret
set.</P>
<P CLASS="western">Ved at s&oslash;rge for, at klasserne har s&aring;
lille afh&aelig;ngighed af hinanden som muligt, kan overskueligheden
af programmet for&oslash;ges, og det bliver lettere at udskifte dele
af programmet.</P>
<P CLASS="western">Det er is&aelig;r vigtigt, hvis man overvejer at
genbruge noget af programkoden i en anden sammenh&aelig;ng, at man
s&oslash;rger for, at bindingerne mellem disse to dele er s&aring;
lav som mulig.</P>
<P CLASS="western">Lav kobling giver ofte flere fordele ud over
genanvendelighed:</P>
<UL>
  <LI><P CLASS="western">Fleksibilitet - den anvendte del kan lettere
  &aelig;ndres eller udskiftes med noget andet.</P>
  <LI><P CLASS="western">Overskuelighed - delene kan forst&aring;s
  uafh&aelig;ngigt af hinanden.</P>
</UL>
<H4 CLASS="western">M&aring;der at f&aring; lav kobling</H4>
<UL>
  <LI><P CLASS="western">Lad klasser have referencer til s&aring; f&aring;
  andre klasser som muligt.</P>
  <LI><P CLASS="western">Specific&eacute;r vigtig funktionalitet i
  interfaces, og lad variabler (og parametre) v&aelig;re af
  interfacets type for at undg&aring; at l&aelig;gge dig fast p&aring;
  en bestemt implementation (dette er beskrevet i <a href='kapitel15.jsp#afsn15.3'>afsnit 15.3</a>).</P>
  <LI><P CLASS="western">Tildel den enkelte klasse et let forst&aring;eligt
  og ensartet ansvarsomr&aring;de (h&oslash;j koh&aelig;sion - se
  <a href='kapitel15.jsp#afsn15.7.2'>afsnit 15.7.2</a>).</P>
</UL>
<H4 CLASS="western">H&oslash;j kobling</H4>
<P CLASS="western">Det modsatte, h&oslash;j kobling, betyder, at
programdelene er afh&aelig;ngige af hinanden, s&aring; man har et
fastl&aring;st program, hvor delene ikke kan isoleres fra helheden og
anvendes i en anden sammenh&aelig;ng.</P>
<P CLASS="western">H&oslash;j kobling opst&aring;r typisk, hvis
ansvarsomr&aring;derne ikke bliver ordentligt klarlagt. Et kendetegn
p&aring; udflydende ansvarsomr&aring;der er, at der er mange klasser
involveret i at varetage en bestemt opgave (spaghetti-programmering).
Koden vil ofte v&aelig;re sv&aelig;rt forst&aring;elig, fordi man
skal s&aelig;tte sig ind i alle de forskellige klasser, som tager del
i udf&oslash;relsen af opgaven.</P>
<P CLASS="western">H&oslash;j kobling kan ogs&aring; opst&aring; ved
meget genbrug (arv er meget h&oslash;j kobling) eller hvis man har
mange sm&aring; metoder, der kalder hinanden meget.</P>
<H3 CLASS="western">15.7.2 <a name='afsn15.7.2'></a>H&oslash;j koh&aelig;sion</H3>
<P CLASS="western">H&oslash;j koh&aelig;sion (sammenh&aelig;ng -
eng.: high cohesion) vil sige, at et objekt har et overskueligt og
let forst&aring;eligt ansvarsomr&aring;de, eller eventuelt flere
ansvarsomr&aring;der, der er t&aelig;t relaterede til hinanden. Jo
flere forskellige ansvarsomr&aring;der et objekt/en klasse har, jo
sv&aelig;rere bliver det at genbruge objektet/klassen.</P>
<H3 CLASS="western">15.7.3 <a name='afsn15.7.3'></a>Indkapsling</H3>
<P CLASS="western">Den nemmeste m&aring;de at sikre lav kobling er
ved at g&oslash;re metoder og variabler, man ikke &oslash;nsker brugt
udefra, utilg&aelig;ngelige udefra.</P>
<P CLASS="western">Vi minder om at:</P>
<UL>
  <LI><P CLASS="western">V<SPAN STYLE="font-weight: medium">ariabler
  og metoder erkl&aelig;ret </SPAN><B>public</B><SPAN STYLE="font-weight: medium">
  altid er tilg&aelig;ngelige inden for og uden for klassen.</SPAN></P>
  <LI><P CLASS="western"><SPAN STYLE="font-weight: medium">Variabler
  og metoder erkl&aelig;ret </SPAN><B>protected</B><SPAN STYLE="font-weight: medium">
  er tilg&aelig;ngelige for alle klasser inden for samme pakke.
  Klasser i andre pakker kan kun f&aring; adgang, hvis de er
  nedarvinger.</SPAN></P>
  <LI><P CLASS="western">Skriver man <B>ingenting</B>, er det kun
  klasser i samme pakke, der har adgang til variablen eller
  metoden.</P>
  <LI><P CLASS="western">Hvis en variabel eller metode er erkl&aelig;ret
  <B>private</B>, kan den kun benyttes inden for samme klasse (og kan
  derfor ikke tilsides&aelig;ttes i en nedarving). Det er det mest
  restriktive.</P>
</UL>
<P CLASS="western">Adgangen kan s&aelig;ttes p&aring; skemaform:</P>
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>
  <COL*>
  <COL*>
  <COL*>
  <COL*>
  <COL*>
  <THEAD>
    <TR VALIGN=TOP>
      <TH HEIGHT=24>
        <P CLASS="western">Adgang</P>
      </TH>
      <TH>
        <P CLASS="western">public</P>
      </TH>
      <TH>
        <P CLASS="western">protected</P>
      </TH>
      <TH>
        <P CLASS="western">(ingenting)</P>
      </TH>
      <TH>
        <P CLASS="western">private</P>
      </TH>
    </TR>
  </THEAD>
  <TBODY>
    <TR VALIGN=TOP>
      <TD HEIGHT=24>
        <P CLASS="western">i samme klasse</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
    </TR>
    <TR VALIGN=TOP>
      <TD HEIGHT=24>
        <P CLASS="western">klasse i samme pakke</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">nej</P>
      </TD>
    </TR>
    <TR VALIGN=TOP>
      <TD HEIGHT=24>
        <P CLASS="western">nedarving i en anden pakke</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">nej</P>
      </TD>
      <TD>
        <P CLASS="western">nej</P>
      </TD>
    </TR>
    <TR VALIGN=TOP>
      <TD HEIGHT=24>
        <P CLASS="western">ej nedarving og i en anden pakke</P>
      </TD>
      <TD>
        <P CLASS="western">ja</P>
      </TD>
      <TD>
        <P CLASS="western">nej</P>
      </TD>
      <TD>
        <P CLASS="western">nej</P>
      </TD>
      <TD>
        <P CLASS="western">nej</P>
      </TD>
    </TR>
  </TBODY>
</TABLE>
<P CLASS="western">Holder man sig inden for samme pakke, er der alts&aring;
<I>ingen</I> forskel mellem public, protected og ingenting. 
</P>
<H3 CLASS="western">15.7.4 <a name='afsn15.7.4'></a>Indkapsling og pakker</H3>
<P CLASS="western">Ud af de ovenst&aring;ende regler kan man
konkludere, at a<SPAN STYLE="font-weight: medium">dgangskontrol ud
over public/private f&oslash;rst bliver interessant, n&aring;r
</SPAN>programmet sp&aelig;nder over flere pakker. 
</P>
<P CLASS="western">S&aring; kan klasserne inden for samme pakke virke
n&aelig;rt sammen (f.eks. &aelig;ndre i hinandens interne variabler),
mens adgangen fra klasserne i de andre pakker er begr&aelig;nset.</P>
<BLOCKQUOTE CLASS="definition-western">For at indkapsle en gruppe
klasser, s&aring;dan at de kan tilg&aring; hinandens metoder, mens
disse metoder ikke er synlige udefra, er man n&oslash;dt til at l&aelig;gge
dem i en pakke for sig</BLOCKQUOTE>
<H4 CLASS="western">Eksempel</H4>
<P CLASS="western"><SPAN LANG="da-DK">Kigger man n&aelig;rmere p&aring;
Funktion-klassen i <a href='kapitel4.jsp#afsn4.7.2'>afsnit 4.7.2</a>, Repr&aelig;sentation af funktioner,
ser man, at dens forskellige nedarvinger (X, Konst, Sin etc.) ikke er
erkl&aelig;ret public, men ingenting. Disse klasser er derfor kun
tilg&aelig;ngelige for klasser, der ligger i den samme pakke (pakken
vp.funktion), s&aring;som klassen Funktionsfortolker beskrevet i
<a href='kapitel4.jsp#afsn4.7.3'>afsnit 4.7.3</a>, Fortolkning af strenge til funktioner. Samtidig er
konstrukt&oslash;ren til Funktion erkl&aelig;ret p&aring;
pakkeniveau, hvilket g&oslash;r, at kun klasser i samme pakke kan
arve fra Funktion.</SPAN></P>
<P CLASS="western">Alt i alt er al logik omkring funktioner
indkapslet i pakken vp.funktion.</P>
<P CLASS="western"><SPAN LANG="da-DK">Klassen Kurvetegner (<a href='kapitel4.jsp#afsn4.7.1'>afsnit 4.7.1</a>,
En komponent til at tegne kurver) ligger i pakken vp og har derfor
ikke adgang til nedarvingerne. Den kan derfor ikke selv kombinere
Funktion-objekter, men m&aring; bruge Funktionsfortolker.</SPAN></P>
<H2 CLASS="western" STYLE="">15.8 <a name='afsn15.8'></a>GRASP</SPAN></H2>
<P CLASS="western">GRASP er nogle grundl&aelig;ggende
tommelfingerregler for, hvordan man skal designe sine klasser. GRASP
st&aring;r for: General Responsibility Assignment Software Patterns
(og selve navnet GRASP angiver samtidig, at det er noget, der er lige
til at tage og bruge).</P>
<P CLASS="western">De forrige afsnit har beskrevet en del af disse
tommelfingerregler, mens andre bliver beskrevet senere i kapitlerne
omkring designm&oslash;nstre.</P>
<P CLASS="western">De 4 af i alt 9 GRASP-regler, der er beskrevet i
denne bog, er:</P>
<UL>
  <LI><P CLASS="western"><SPAN LANG="da-DK">Ekspert (eng.: Information
  Expert) - beskrevet i <a href='kapitel15.jsp#afsn15.6.2'>afsnit 15.6.2</a>.</SPAN></P>
  <LI><P CLASS="western">Skaber (eng.: Creator) - beskrevet i afsnit
  15.6.3.</P>
  <LI><P CLASS="western">Lav kobling - beskrevet i <a href='kapitel15.jsp#afsn15.7.1'>afsnit 15.7.1</a>.</P>
  <LI><P CLASS="western">H&oslash;j koh&aelig;sion (sammenh&aelig;ng)
  - beskrevet i <a href='kapitel15.jsp#afsn15.7.2'>afsnit 15.7.2</a>.</P>
</UL>
<H2 CLASS="western">15.9 <a name='afsn15.9'></a>Introduktion til designm&oslash;nstre</SPAN></H2>
<P CLASS="western">Et designm&oslash;nster (eng.: design pattern) er
en navngiven beskrivelse af, hvordan et givent problem kan l&oslash;ses
og konsekvenserne af denne m&aring;de at l&oslash;se problemet p&aring;.</P>
<P CLASS="western">Id&eacute;en er, at man m&aring;ske senere i et
andet program kan genbruge det samme designm&oslash;nster til at l&oslash;se
et lignende problem (selve begrebet m&oslash;nster angiver jo, at det
er noget, som gentages).</P>
<P CLASS="western">Designm&oslash;nstre hj&aelig;lper med:</P>
<UL>
  <LI><P CLASS="western"><SPAN LANG="da-DK">at give id&eacute;er til
  godt design, s&aring;dan at n&aring;r man st&aring;r over for en
  problemstilling ikke skal &quot;opfinde den dybe tallerken&quot;
  igen og kan undg&aring; de mest almindelige faldgruber</SPAN>.</P>
  <LI><P CLASS="western"><SPAN LANG="da-DK">at give programm&oslash;rer
  en klar, f&aelig;lles begrebsramme, der g&oslash;r det </SPAN>lettere
  at forklare/dokumentere hvad man har lavet.</P>
</UL>
<P CLASS="western">Ofte vil designm&oslash;nstre give id&eacute;er
til, hvordan man kan formindske graden af bindinger (kobling) mellem
forskellige dele af programmet. Programkoden deles ofte op i to dele:</P>
<UL>
  <LI><P CLASS="western">Den del, der <B>anvender</B> en bestemt anden
  del. Denne del kaldes kaldes 'klienten'. 
  </P>
</UL>
<P CLASS="western">Den del, der <B>anvendes</B>. Denne del er m&aring;ske
generel anvendelig, m&aring;ske endda en del af et standardbibliotek.</P>
<H3 CLASS="western">15.9.1 <a name='afsn15.9.1'></a>Designm&oslash;nstre ber&oslash;rt i de
f&oslash;lgende kapitler</H3>
<P CLASS="western">I <a href='kapitel16.jsp'>kapitel 16</a>, Skabende designm&oslash;nstre,
behandles:</P>
<UL>
  <LI><P CLASS="western">Fabrikeringsmetode - en metode, der
  fabrikerer objekter for klienten (i stedet for at klienten selv
  opretter dem med new)</P>
  <LI><P CLASS="western">Fabrik - et objekt med en fabrikeringsmetode</P>
  <LI><P CLASS="western">Singleton - sikring af, at der kun eksisterer
  &eacute;t objekt af en bestemt slags</P>
  <LI><P CLASS="western">Abstrakt Fabrik/Toolkit - er en Fabrik med
  nedarvinger, der s&oslash;rger for objektoprettelsen. Hvilken
  nedarving der anvendes, bestemmes af en fabrikeringsmetode</P>
  <LI><P CLASS="western">Bygmester - simplificerer oprettelsen af
  nogle relaterede objekter ved at oprette og konfigurere objekterne
  (evt. trinvist) for klienten</P>
  <LI><P CLASS="western">Prototype - objekter oprettes ud fra
  eksisterende skabelon-objekter</P>
  <LI><P CLASS="western">Objektpulje - genbrug de samme objekter igen
  og igen ved at huske dem i en pulje</P>
</UL>

<P CLASS="western">I <a href='kapitel17.jsp'>kapitel 17</a>, Hyppigt anvendte designm&oslash;nstre,
behandles:</P>
<UL>
  <LI><P CLASS="western">Proxy - f&aring; metodekald til at g&aring;
  gennem et mellem-objekt (proxyen), der modtager metodekald p&aring;
  vegne af (fungerer som en erstatning) for det rigtige objekt og
  kalder videre i det rigtige objekt</P>
  <LI><P CLASS="western">Herunder Virtuel Proxy/Doven Initialisering -
  udskyde oprettelsen af det rigtige objekt til f&oslash;rste gang,
  der er brug for det</P>
  <LI><P CLASS="western"><SPAN LANG="da-DK">Adapter - et hj&aelig;lpeobjekt,
  der f&aring;r et objekt til at passe ind i et system ved at fungere
  som omformer mellem objektet og systemet</SPAN></P>
  <LI><P CLASS="western">Iterator - hj&aelig;lper med at genneml&oslash;be
  nogle data</P>
  <LI><P CLASS="western">Facade - forenkler brugen af et s&aelig;t
  objekter ved at give en simplificeret gr&aelig;nseflade til dem</P>
  <LI><P CLASS="western">Observat&oslash;r/Lytter - at objekter kan
  'abonnere' p&aring;, at en ting (h&aelig;ndelse) sker</P>
  <LI><P CLASS="western">Dynamisk Binding - at underst&oslash;tte
  &quot;plugin&quot;-klasser, der kan indl&aelig;ses under k&oslash;rslen
  og dermed udvide programmet, efter at det er skrevet</P>
</UL>

<P CLASS="western">I <a href='kapitel18.jsp'>kapitel 18</a>, Andre designm&oslash;nstre,
behandles:</P>
<UL>
  <LI><P CLASS="western">Uforanderlig - objektet kan ikke &aelig;ndres,
  n&aring;r det f&oslash;rst er oprettet</P>
  <LI><P CLASS="western">Fluev&aelig;gt - begr&aelig;ns antallet af
  objekter ved at s&oslash;rge for, at der ikke bliver oprettet
  objekter med de samme data. I stedet er der mange referencer til de
  samme (unikke) objekter</P>
  <LI><P CLASS="western">Filter - objekter, der &quot;filtrerer&quot;
  en str&oslash;m af data. Filtrene kan kombineres vilk&aring;rligt</P>
  <LI><P CLASS="western">Lagdelt Initialisering - klienten opretter et
  objekt direkte, og dette objekt opretter eller fremskaffer det, der
  i virkeligheden skal bruges og videredelegerer det meste af arbejdet
  til det</P>
  <LI><P CLASS="western">Komposit/Rekursiv Komposition - skabe et
  meget fleksibelt objekthierarki, ved at definere objekter, der kan
  indeholde andre objekter inkl. sin egen slags</P>
  <LI><P CLASS="western">Kommando - registr&eacute;r brugeren
  &aelig;ndringer af data, s&aring;dan at de kan fortrydes igen.</P>
</UL>

<P CLASS="western">I <a href='kapitel19.jsp'>kapitel 19</a>, Model-View-Controller-arkitekturen,
behandles et designm&oslash;nster beregnet til programmer med en
brugergr&aelig;nseflade, der anbefaler at man opdeler programmet i en
datamodel, som repr&aelig;senterer data, forretningslogikken og de
bagvedliggende beregninger, en pr&aelig;sentation af data over for
brugeren, og en kontrol-del, der giver brugeren mulighed for at &aelig;ndre
i data.</P>

<DIV ID="sdfootnote1">
  <P CLASS="sdfootnote-western"><A CLASS="sdfootnotesym" NAME="sdfootnote1sym" HREF="#sdfootnote1anc">1</A>Ordene
  &quot;amerikansk&quot; og &quot;skandinavisk&quot; tankegang bruges
  bl.a. i et citat af Erik Ernst i artiklen &quot;The Origins of
  Object Orientation&quot;, som kan findes p&aring;
  http://ootips.org/history.html</P>
</DIV>
<DIV ID="sdfootnote2">
  <P CLASS="sdfootnote-western"><A CLASS="sdfootnotesym" NAME="sdfootnote2sym" HREF="#sdfootnote2anc">2</A>Se
  f.eks. <a href='kapitel1.jsp'>kapitel 1</a>, Samlinger af data, hvor ArrayList og LinkedList
  let kan skiftes ud med hinanden, fordi deres f&aelig;lles
  funktionalitet er defineret i interfacet List.</P>
</DIV>
<DIV ID="sdfootnote3">
  <P CLASS="sdfootnote-western"><A CLASS="sdfootnotesym" NAME="sdfootnote3sym" HREF="#sdfootnote3anc">3</A>Egentlig
  signaturen, dvs. metodenavn og antal og type af parametre.</P>
</DIV>
<DIV ID="sdfootnote4">
  <P CLASS="sdfootnote-western"><A CLASS="sdfootnotesym" NAME="sdfootnote4sym" HREF="#sdfootnote4anc">4</A>Det
  kunne f.eks. v&aelig;re StakMedNedarving og StakMedDelegering.</P>
</DIV>

<a href='http://javabog.dk/'>javabog.dk</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel14.jsp'>&lt;&lt; forrige</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='indhold.jsp'>indhold</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel16.jsp'>n&aelig;ste &gt;&gt;</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kode/'>programeksempler</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='../index_VP.html'>om bogen</a>
<hr>
<font size=-2>http://javabog.dk/ - <b></b> af Jacob Nordfalk.
<br>
  Licens og kopiering under <a href='http://www.linuxbog.dk/licens.html'>&Aring;ben Dokumentlicens</a> (&Aring;DL)
  hvor intet andet er nævnt (71% af værket).
</font>
<br>
Ønsker du at se de sidste 29% af dette værk (362838 tegn)
skal du købe bogen. Så får du pæne figurer og layout, stikordsregister og en trykt bog med i købet.
<!-- netlæser: Wget/1.10, autoHent: true  -->
     

</body>
</html>
