Lite om god OOP-design. Det mesta är en repetition av vad som sagts tidigare.
Utgå från vad klasserna representerar. En klass representerar ofta
något konkret och fysiskt. Exempel: Klasserna Person
, Employee
,
Furnace
från avsnitt 1.
I Javas standardbibliotek hittar vi till exempel Map
(en slags
tabell), List
(en lista), JFrame
(ett fönster på skärmen).
I samtliga fall kan man (med lite vilja) tänka sig att klasserna svarar mot nåt konkret och fysiskt.
Undvik att definiera klasser som bara samlar ihop diverse relevanta attribut.
Klasser som beskriver handlingar är sällan bra.
Namngivning är viktigt. Namnet på klasser ska förstås beskriva vad
en instans av klassen representerar. Använd alltid ental—en klass
som beskriver personer ska heta Person
, inte Persons
.
Vad återstår när man har valt klassnamn? Det roliga! Du måste hitta en representation. Välj vilka attribut (instansvariabler) som är relevanta för klassen och programmet. Definiera operationer på klassen (metoder).
Som jag skrev tidigare (i avsnittet om klasser) bör arv endast
användas när klasserna är konceptuellt relaterade. Man kan till
exempel tänka sig att en Employee
är en slags Person
. Därför kan
det vara rimligt att låta klassen Employee
vara en subklass till
klassen Person
.
Man vill också att det ska fungera implementationsmässigt att låta en klass ärva av en annan. Exempel: en kvadrat är en slags rektangel. Ändå blir det konstigt att låta klassen kvadrat vara en subklass till klassen rektangel; en kvadrat har ju bara en instansvariabel (längden på en sida) men en rektangel har längd och bredd. Om kvadrat ärver av rektangel får ju kvadrat en 'onödig' instansvariabel. Här passar det bättre att definiera en ny superklass som har de egenskaper som rektanglar och kvadrater (och andra figurer) har gemenamt. Vad borde den nya superlassen heta?
För variabler och metoder är namngivning också viktig. Vad beskrier variabeln? Vad beskriver metoden?
För en klass Person
kan vi ha instansvariabler age
och
name
. age
är förstås personen ålder och name
personens namn. I
båda fallen beskriver instansvariabeln nånting om personen. (En
instansvariabel age
är kanske inte superbra—personer blir ju äldre
ibland och då måste man uppdatera objektet. Vad skulle man kunna göra
istället?)
Metoder bör beskriva handlingar. Vanligtvis är metoder kopplade till något objekt i en klass (när jag vill vara tydlig om att det är såna metoder jag talar om kallar jag dem instansmetoder). Här har varje metodanrop en mottagare, och det följer omedelbart att metoden är en operation på det objektet.
Några metoder i Javas standardbibliotek: toString()
tar fram en
strängrepresentation av objektet. Notera att metoden inte tar några
parametrar; all information man behöver finns ju i objektet. size()
ger antalet element i en lista. add(Object x)
används för att addera
nåt till en lista. (Det finns flera metoder add()
i Javas
standardbibliotek. Du kan också definiera egna metoder add
för de
klasser du definierar.)
Om en klass har en instansvariabel (till exempel name
) brukar man
ofta definiera metoder för att kunna ta fram värdet på variabeln
(getName()
) och uppdatera variabeln
(setName(String newName)
. Försök att följa denna form om du
definierar metoder för att ta reda på eller ändra värdet av en
instansvariabel. Omvänt, om en metod heter nånting med get eller set
väntar sig nog en läsare att den fungerar som i exemplet. Om du vill
implementera ett annat beteende, välj ett annat namn på metoden.
Konstruktorer är avsedda att användas för konstruktion och initiering av objekt. Undvik att använda konstruktorerna till annat. En konstruktor bör inte innehålla kod som inte handlar om konstruktion och initiering.
Instansvariabler för en klass bör inte användas av kod i andra
klasser. För att försäkra dig om att det inte sker av misstag kan du
deklarera variabeln private
. (Detta begrepp beskrivs i avsnitt 4.)
Klasser och metoder bör inte vara för stora och komplicerade. Om en klass blir stor bör du överväga att dela upp den i mindre klasser. (Hur skulle det gå till?)
På samma sätt bör en metod inte bli för stor. Även här brukar det vara ganska lätt att hitta naturliga sätt att dela upp metoden i mindre metoder.