19
Opphavsrett: Forfatter og Stiftelsen TISIP Avdeling for informatikk og e-læring, Høgskolen i Sør-Trøndelag Objektorientering i VB videregående Oppdatert av Atle Nes Objektorientering i VB – videregående Resymé: Denne leksjonen tar opp flere detaljer knyttet til bruk av klasser. Et av de viktigste prinsippene innen objektorientering, er innkapsling. Hva er det, og hvordan gjøres det i praksis? 10.1. PROBLEMATIKKEN KNYTTET TIL INNKAPSLING ....................................................................................... 2 10.1.1. Eksempel på bruk av Public objektvariabler ................................................................................. 2 10.1.2. Public objektvariabler er ikke god programmeringsskikk ............................................................. 3 10.2. MULIG TILNÆRMING NR 1 OFFENTLIGE METODER ............................................................................... 4 10.2.1. Egen metode for å sette objektvariabler ........................................................................................ 4 10.2.2. Forklaring til metoden lagreInformasjon().................................................................................... 5 10.2.3. Bruk av metoden lagreInformasjon() ............................................................................................. 5 10.2.4. Bruk av mange metoder for å lagre og hente informasjon ............................................................ 7 10.2.5. Metoder kan gjøre det du vil også validering ............................................................................. 8 10.2.6. Oppsummert: Hvorfor metoder?.................................................................................................. 10 10.3. MULIG TILNÆRMING NR 2 KONSTRUKTØRER..................................................................................... 10 10.3.1. Hva skjer når vi lager et nytt objekt?........................................................................................... 10 10.3.2. Konstruktører lager og fyller objektet på en gang ....................................................................... 11 10.3.3. En enda kortere syntaks ............................................................................................................... 12 10.3.4. Overloading ................................................................................................................................. 13 10.4. MULIG TILNÆRMING NR 3 BRUK AV PROPERTY ................................................................................. 14 10.4.1. Property brukes primært til å hente og endre verdi i objektvariabler ......................................... 14 10.4.2. Forklaring til Get og Set .............................................................................................................. 15 10.4.3. Detaljer og ytterligere forklaring ................................................................................................ 16 10.4.4. Hva har en skarve TextBox og en Label å gjøre med en Aha-opplevelse? .................................. 16 10.4.5. En siste Aha-opplevelse ............................................................................................................... 18

Objektorientering 2

Embed Size (px)

Citation preview

Page 1: Objektorientering 2

Opphavsrett: Forfatter og Stiftelsen TISIP

Avdeling for informatikk og e-læring, Høgskolen i Sør-Trøndelag

Objektorientering i VB – videregående Oppdatert av Atle Nes

Objektorientering i VB – videregående Resymé: Denne leksjonen tar opp flere detaljer knyttet til bruk av klasser. Et av de viktigste prinsippene innen

objektorientering, er innkapsling. Hva er det, og hvordan gjøres det i praksis?

10.1. PROBLEMATIKKEN KNYTTET TIL INNKAPSLING ....................................................................................... 2 10.1.1. Eksempel på bruk av Public objektvariabler ................................................................................. 2 10.1.2. Public objektvariabler er ikke god programmeringsskikk ............................................................. 3

10.2. MULIG TILNÆRMING NR 1 – OFFENTLIGE METODER ............................................................................... 4 10.2.1. Egen metode for å sette objektvariabler ........................................................................................ 4 10.2.2. Forklaring til metoden lagreInformasjon() .................................................................................... 5 10.2.3. Bruk av metoden lagreInformasjon() ............................................................................................. 5 10.2.4. Bruk av mange metoder for å lagre og hente informasjon ............................................................ 7 10.2.5. Metoder kan gjøre det du vil – også validering ............................................................................. 8 10.2.6. Oppsummert: Hvorfor metoder? .................................................................................................. 10

10.3. MULIG TILNÆRMING NR 2 – KONSTRUKTØRER ..................................................................................... 10 10.3.1. Hva skjer når vi lager et nytt objekt? ........................................................................................... 10 10.3.2. Konstruktører lager og fyller objektet på en gang ....................................................................... 11 10.3.3. En enda kortere syntaks ............................................................................................................... 12 10.3.4. Overloading ................................................................................................................................. 13

10.4. MULIG TILNÆRMING NR 3 – BRUK AV PROPERTY ................................................................................. 14 10.4.1. Property brukes primært til å hente og endre verdi i objektvariabler ......................................... 14 10.4.2. Forklaring til Get og Set .............................................................................................................. 15 10.4.3. Detaljer og ytterligere forklaring ................................................................................................ 16 10.4.4. Hva har en skarve TextBox og en Label å gjøre med en Aha-opplevelse? .................................. 16 10.4.5. En siste Aha-opplevelse ............................................................................................................... 18

Page 2: Objektorientering 2

Objektorientering i VB – videregående side 2 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

10.1. Problematikken knyttet til innkapsling

Vi så i leksjonen om grunnleggende objektorientering, at en klasse har objektvariabler

(egenskaper) og metoder. Et eksempel på en klasse er Person, og denne personen har kanskje

en vekt, et navn og en høyde. Det er mulig å finne en såkalt ”body mass index” til personen

basert på en utregning av vekt deltpå høyden (i meter) opphøyd i andre. I stedet for å

registrere body mass index, passer det å lage en metode som regner denne ut ved behov.

Basisinformasjon om vekt og høyde kan også brukes til mye annet rart.

Vi skal nå se hvordan vi kan gjøre koden vår mer modulær og selvstendig. Dette er et ønske

innen objektorientering.

10.1.1. Eksempel på bruk av Public objektvariabler

Dersom vi ikke tar med noen metoder, vil klassen Person kunne se slik ut:

Public Class Person

Public navn As String 'navnet på personen

Public vekt As Double 'antall kg

Public hoyde As Double 'antall cm

'Tar ikke med noen metoder her for oversiktens skyld

End Class

Husk at en klasse gjerne ligger i en egen fil, og uansett mellom kodeordene Public

Class KlassensNavn og End Class. Siden vi har angitt kodeordet Public foran

objektvariablene navn, vekt og hoyde, vil disse objektvariablene kunne brukes utenfor filen

(faktisk også på tvers av prosjekter om en vil det, så lenge prosjektene ligger i samme

solution). Det betyr at vi kan skrive følgende under for eksempel Button1 i Form1:

Private Sub Button1_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button1.Click

'Lager en ny instans av klassen Person

Dim lise As Person

lise = New Person

'Registrerer navn, høyde og vekt for Lise

lise.vekt = 62

lise.navn = "Lise Nordmann"

lise.hoyde = 170

MsgBox(lise.navn & " er " & lise.hoyde & " høy")

End Sub

Her har vi laget et nytt objekt som heter lise. Lise må ha en alder, et navn og en høyde. Det

er nødvendig å fylle objektet lise sine objektvariabler med informasjon. Etter å ha gjort dette,

henter vi ut informasjon om objektet (navn og høyde) og skriver ut i en meldingsboks.

Page 3: Objektorientering 2

Objektorientering i VB – videregående side 3 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Figur 1: Objektet lise (til høyre) som er en instans av den generelle klassen Person (til venstre).

10.1.2. Public objektvariabler er ikke god programmeringsskikk

Vi kan bruke punktumnotasjonen objekt.objektvariabel = "verdi" for å foreta

en tilordning til en objektvariabel. Dette fungerer i vårt eksempel ene og alene fordi vi har satt

Public foran navnet på objektvariablene i klassen Person. Dersom vi hadde satt Dim

navn As String, så ville det ikke fungert å skrive lise.navn = "Lise

Nordmann" under Button1_Click. Dim er en såkalt modifikator som angir en lokal

variabel, mens Public altså er en modifikator som gjør at en variabel (eller en klasse eller en

metode/funksjon) blir tilgjengelig overalt.

Her er et interessant apropos for den som er interessert. Private er nemlig en

mellomting mellom Public og Dim. Private betyr dermed at variabelen er tilgjengelig

overalt innenfor klassen, men ikke utenfor. Det var forresten slik vi kunne lage globale

variabler, matriser og funksjoner tidligere i kurset. Vi satte da kodeordet Private foran globale

variabler, for eksempel slik: Private matrise(4) as Integer. Vi plasserte slike

globale ting øverst i koden, før alle knappene våre. Den observante leser har trolig sett at det i

alle programmer vi har laget til nå i hele kurset, helt øverst har stått Public Class

Form1, og helt nederst har stått en tilsvarende End Class. Det vil si at når vi lager en

knapp ved å dobbeltklikke på koden til Form1, så er vi egentlig bare kommet til koden som

angir klassen Form1... Alt av kode til knappene våre etc. ligger i denne klassen, og dermed vil

Private-variabler få en global funksjon.

Så tilbake til problemstillingen: Vi kan deklarere objektvariablene som Public, og vi får da

tilgang til å endre og sette disse fra utsiden. Det er derimot noen ulemper med en slik

fremgangsmåte:

Dersom vi senere ønsker å endre klassens objektvariabler til å hete noe annet, for

eksempel ikke ”navn”, men ”fornavn”, så betyr det at vi må endre koden også i

Button1_Click. Klassen har plutselig en mindre smart avhengighet til der hvor

objektene brukes i praksis.

Validering av data overlates til den som programmerer objektene, ikke den som har

programmert klassen. Dersom noen forsøker å lage et nytt personobjekt og gi en

feilaktig verdi, som vist her, vil programmet kræsje siden klassen forventer en Double-

verdi:

Dim kari as Person

kari = New Person

kari.vekt = "vet ikke" 'her kræsjer programmet fordi datatypen er feil

!

Page 4: Objektorientering 2

Objektorientering i VB – videregående side 4 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Generelt gjelder prinsippet innen objektorientering at en skal forsøke å innkapsle koden.

Klassen Person beskriver karakteristika og aksjoner som gjelder for en generell person. Det er

om å gjøre å holde dette så generelt som mulig. En bør derfor unngå å kreve at objektvariabler

refereres til direkte fra koden der hvor objektene lages og brukes.

Likevel er det selvsagt nødvendig å si at for eksempel Ole er 83 kg og 192 cm. Hvis ikke, kan

vi ikke finne ut hva Ole sin ”body mass index” er, og vi kan heller ikke gjøre noe annet

fornuftig med Ole. Det er altså essensielt å kunne endre objektvariablene til et objekt, uten å

måtte bruke Public-variabler i klassens kode. Hvordan får vi til dette?

Figur 2: Ønsker at koden i for eksempel Button1_Click skal ha mulighet til å få lagret informasjon inn i objektet ”ole”, uten å bryte med prinspper rundt innkapsling.

10.2. Mulig tilnærming nr 1 – offentlige metoder

En klasse kan ha objektvariabler og metoder. I stedet for å bruke Public objektvariabler, og

sette disse der objektene brukes ved hjelp av ole.vekt = 83, kan vi jo lage lages en

metode som får i oppdrag å sette Ole sin vekt. Metoder skal vanligvis kunne kalles opp

utenfra klassen, og disse er derfor stort sett deklarert som Public. Selve metoden ligger inne i

klassen, og det betyr at den har tilgang til alle Private-variabler. Det betyr at vi kan lage oss en

Public-metode, og la den få i oppdrag å registrere verdier i objektvariablene!

10.2.1. Egen metode for å sette objektvariabler

La oss nå lage en ny, modifisert og bedre utgave av klassen Person:

Public Class Person

Private navn As String 'objektvariablene er kun tilgjengelige

Private vekt As Double 'internt i denne klassen

Private hoyde As Double 'siden de er deklarert som Private

Public Sub lagreInformasjon(ByVal navn As String, _

ByVal kg As Double, _

ByVal cm As Double)

'Metode for å registrere data om navn, vekt og høyde.

'Fyller objektvariablene med innholdet som kommer fra argumentene

vekt = kg 'argumentet heter "kg" mens objektvariabelen heter "vekt"

hoyde = cm

Me.navn = navn

'dersom argumentet og objektvariabelen heter det samme,

'må kodeordet Me. brukes for å angi objektvariabelen

End Sub

End Class

Page 5: Objektorientering 2

Objektorientering i VB – videregående side 5 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Her har vi laget en metode som har én eneste oppgave i livet:

Motta informasjon om et navn, en vekt og en høyde.

Plassere denne informasjonen inn i dette objektets tilsvarende objektvariabler.

10.2.2. Forklaring til metoden lagreInformasjon()

Det er noen detaljer som bør forklares i koden til metoden lagreInformasjon()

Vi har brukt kodeordet Sub, siden dette er en metode som ikke skal returnere noen

verdi. Vi kunne brukt Function, men da skal vi egentlig returnere en verdi, og det

er ikke nødvendig her, så da bruker vi helst Sub.

Metoden har tre argumenter. Disse heter navn, kg og cm. Dette er på en måte

inngangsporten for informasjon som skal inn til metoden og behandles der inne. Hvis

alt er på en laaaaang linje, så går det greit. Dersom du vil bryte på flere linjer, må

understrek-tegnet brukes (som vi har gjort).

Figur 3: Visual Studio hjelper til ved bruk av metoder. Her vises hvilke argumenter (og datatyper) som må fylles ut.

Det metoden skal gjøre, er å plassere informasjonen som kommer fra hvert av

argumentene inn i riktig objektvariabel. Objektvariabelen vekt skal få den verdien

som sendes gjennom argumentet kg. Objektvariabelen hoyde skal få den verdien

som sendes gjennom argumentet cm.

Merk at objektvariabelen navn skal få den verdien som sendes inn gjennom

argumentet navn. Problemet er at begge heter ”navn”. Her har vi en situasjon som

må håndteres. Hvordan skal VB vite hva som er argumentet, og hva som er

objektvariabel i den koden som kommer inne i selve metoden? Måten å skille dem fra

hverandre på, er å bruke kodeordet Me og et punktum foran objektvariabelen. ”Me”

er nemlig et kodeord som henspeiler tilbake på akkurat dette objektet. Hvorfor brukes

Me. kun i den siste setningen? Fordi de andre to argumentene ikke har samme navn

som objektvariablene, og derfor er det ingen konflikt ute og går. Hva skal en så bruke?

Dette er helt valgfritt. I stedet for å pønske ut synonymer av objektvariablene som

navn på argumentene, kan en med fordel bruke Me. Det er egentlig en smakssak, men

Me er såpass vanlig at du bør kjenne til muligheten slik at du forstår andres kode.

Det siste som er verdt å merke seg, er at denne metoden er deklarert som Public. Det er

veldig viktig, og betyr at den kan kalles opp fra et helt annet sted, for eksempel under

Button1_Click i Form1. Det er nettopp dette vi ønsker. Public er helt nødvendig å

bruke for å angi korrekt tilgang til denne metoden.

10.2.3. Bruk av metoden lagreInformasjon()

La oss nå se hvordan metoden lagreInformasjon() kan brukes i praksis. Vi har her

ganske enkelt dobbeltklikket på en knapp i Form1, og kommer da til koden bak

Page 6: Objektorientering 2

Objektorientering i VB – videregående side 6 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Button1_Click(...). Vi oppretter to objekter for å tydeliggjøre at hvert objekt er

uavhengig av hverandre (forskjellige instanser av samme klasse).

Public Class Form1

'Program som bruker klassen Person og lager to personer

Private Sub Button1_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button1.Click

'Lager to objektvariabler av type Person

Dim lise As Person

lise = New Person

Dim ole As Person

ole = New Person

'Registrerer navn, vekt og høyde for Ole

ole.lagreInformasjon("Ole Nordmann", 83, 192)

'Registrerer navn, vekt og høyde for Lise

lise.lagreInformasjon("Lise Nordmann", 62, 170)

End Sub

End Class

Legg merke til forskjellen på hvordan objektvariablene navn, vekt og hoyde får innhold denne

gangen, sammenliknet med tidligere. Vi ønsker å registrere objektet ole sitt navn, vekt og

høyde. Vi har ikke tilgang til objektvariablene som ligger inne i objektet, siden disse er lokale

(deklarert med Private). Vi har derimot en metode som kan gjøre jobben for oss, og kaller

derfor opp lagreInformasjon() med de riktige verdiene som argumenter.

Figur 4: Illustrasjon over dataflyten når Public-metoden lagreInformasjon() kalles opp i Button1_Click. Tenk over at objektet er en instans av klassen Person. Objektvariablene er

Page 7: Objektorientering 2

Objektorientering i VB – videregående side 7 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Private, men siden metoden ligger i samme klasse, har den tilgang til å skrive til objektvariablene.

Det at objektvariabler gjerne deklareres i klassen som Private, mens metoder deklareres

som Public, er veldig ofte tilfelle innen OOP-løsninger. Objektets variabler blir da lokale,

og eksponeres ikke noe annet sted enn internt i objektet. Metodene blir derimot offentlige, og

eksponeres utenfor objektet. Det betyr at vi kan lage metoder som lar oss – fra utsiden – hente

ut eller endre den tilsynelatende utilgjengelige informasjonen i objektvariablene. Dette

prinsippet er viktig å forstå. Ikke fall for fristelsen å plassere Public overalt bare for at det

fungerer. Det vil skape problemer i lengden. Prøv heller å forstå betydningen av disse

modifikatorene først som sist.

10.2.4. Bruk av mange metoder for å lagre og hente informasjon

Vi har nå sett på hvordan vi kan lage en metode for å registrere informasjon i et objekt (i

objektvariablene). Vår metode registrerte informasjon i tre objektvvariabler i samme sleng.

Det er ingenting i veien for å ha flere metoder som registrerer informasjon. Vi kunne

tilsvarende hatt metoder for å lese ut verdien av objektvariablene. Om vi følger en slik

kodestil, vil vi få dobbelt så mange metoder som antall private objektvariabler (altså 6 i vårt

tilfelle).

Public Class Person

Private navn As String 'objektvariablene er kun tilgjengelige

Private vekt As Double 'internt i denne klassen

Private hoyde As Double 'siden de er deklarert som Private

Public Sub lagreNavn(ByVal navn As String)

'Metode for å registrere navnet i riktig objektvariabel

Me.navn = navn

End Sub

Public Sub lagreVekt(ByVal vekt As Double)

Me.vekt = vekt

End Sub

Public Sub lagreHoyde(ByVal hoyde As Double)

Me.hoyde = hoyde

End Sub

Public Function hentNavn() as String

return navn

End Function

Public Function hentVekt() as Double

return vekt

End Function

Public Function hentHoyde() as Double

return hoyde

End Function

End Class

Legg merke til hvordan de tre første metodene er deklarert som Sub. Disse skal lagre det

som kommer inn i argumentet i riktig objektvariabel. De tre siste metodene er derimot

deklarert som Function. Disse skal returnere verdien til de ulike objektvariablene. Legg

Page 8: Objektorientering 2

Objektorientering i VB – videregående side 8 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

merke til at returtypen for hver metode er satt til det samme som typen på tilhørende

objektvariabel.

Figur 5 viser eksempel på kode som bruker av disse 6 metodene til å lagre og lese

informasjonen i objektvariablene:

Figur 5: Kode bak Button2_Click bruker metoder som er definert i klassen, til å lagre informasjon i objektet ”knut” og hente ut informasjon fra objektet ”knut”.

10.2.5. Metoder kan gjøre det du vil – også validering

Nå tenker du kanskje: ”Dette er jo veldig tungvindt. Hvorfor bruke OOP når det blir så utrolig

mye mer kode å skrive, og så mange ting å holde orden på?”

Fordelene med OOP er mange. Joda, det er riktig at det kan bli mye kode for å løse et lite

problem, men det blir faktisk motsatt (mye mindre kode) når du skal løse større problemer. I

tillegg vil du oppleve gevinster som går på sikkerhet, modularitet, gjenbrukbarhet og

liknende. Du vil kunne bli mer en komponent-programmerer enn en detalj-programmerer. Det

øker mulighetene for bedre produktivitet, effektivitet, kvalitet, sikkerhet og så videre.

Med så mye kode å skrive (to metoder for hver objektvariabel som er Private) kan det være

fristende å lage objektvariablene som Public og slik spare plass. La oss gå gjennom et

eksempel som tar opp et viktig motargument mot å gjøre det så lett som mulig.

Tenk deg at du i knappen Button3_Click i Form1 ønsker å opprette et nytt objekt.

Det er personen Karl Anton det er snakk om. Du lager objektet ka og vil så registrere

høyden på ka. Du skriver inn 1.80 i koden fordi Karl Anton er 1 meter og 80 cm høy.

Problemet er bare at objektvariabelen hoyde bør ha høyden i antall cm. Hvorfor? Fordi

metoden finnBMI() som brukes til å regne ut ”body mass index” (BMI) forventer at

høyden som er lagret i objektet, er oppgitt i antall cm. Denne metoden tar nemlig høyden og

deler på 100. Dersom du ved en feiltakelse registrerer høyden som antall meter i stedet for

antall centimeter, blir det feil å dele på 100 i metoden.

Page 9: Objektorientering 2

Objektorientering i VB – videregående side 9 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Figur 6: Metoden finnBMI() tar antall cm og deler på 100, før den regner ut BMI.

Denne situasjonen er skummel. Objektvariabelen hoyde er av type Double, så det går

bra å registrere både 180 og 1.80. Hvis en registrerer 180, vil alt gå bra i det en kaller opp

metoden finnBMI(). Hvis en registrerer 1.80, vil finnBMI() klare å regne ut en BMI,

men verdien vil være veldig feil.

Vi kan skrive om metoden til å ikke dele på 100, men da har vi akkurat samme situasjon: en

person som glemmer seg og skriver 180 i stedet for 1.80, vil da oppleve feilen.

Det som er lurt her, er å validere at verdien er riktig før objektvariabelen får innhold. Vi kan

validere på to steder:

I Button3_Click rett før metoden kalles opp. Vi kaller bare opp metoden dersom tallet

er riktig skrevet inn. Dette får vi til med en If-test.

I Klassen Person, nærmere bestemt i metoden lagreHoyde(). Dette får vi til med

en If-test.

La oss nå se hvordan vi kan faktisk tillate brukeren å skrive enten antall meter eller antall

centimeter!

Public Class Person

Private navn As String 'objektvariablene er kun tilgjengelige

Private vekt As Double 'internt i denne klassen

Private hoyde As Double 'siden de er deklarert som Private

'De andre metodene er fjernet her for oversiktens skyld.

Public Sub lagreHoyde(ByVal hoyde As Double)

'Antar at meter brukes hvis tallet er lite

If hoyde < 10 Then

Me.hoyde = hoyde * 100

Else

Me.hoyde = hoyde 'Hvis stort tall, så lagres tallet direkte

End If

End Sub

End Class

Dersom vi nå kaller opp metoden slik:

Dim ka As New Person

ka.lagreHoyde(1.80)

ka.lagreVekt(78)

MsgBox("BMI-verdien til Karl Anton er " & ka.finnBMI())

Page 10: Objektorientering 2

Objektorientering i VB – videregående side 10 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

så vil resultatet bli at BMI-verdien er ca. 24,07. Dersom vi kaller med

ka.lagreHoyde(180) så får vi samme resultat. Hvis vi ikke hadde foretatt validering,

ville verdien blitt ca 240740, altså et helt feil tall (regn ut selv om du er i tvil).

10.2.6. Oppsummert: Hvorfor metoder?

Fordelen med metode-fremgangsmåten blir åpenbar i følgende scenario:

1. Du har først en metode som setter vekt direkte

2. Du lager et program med mange knapper i mange forms. Rundt om kring i disse har

du behov for å lage nye personer, for eksempel ”Petra” og ”Trulte”. Du oppretter

typisk petra og kaller opp metoden petra.lagreVekt(100) for å få

plassert inn riktig vekt i objektvariabelen til objektet petra. Du skal så lagre for

objektet trulte, og skriver trulte.lagreVekt(859). Du skulle egentlig

skrive 85.9 men, glemte kommaet (punktumet).

3. Du oppdager feilen med en gang, og tenker at ”jeg kan jo rette opp til å være 85.9,

men hva om jeg gjør samme feil senere? La meg heller fikse metoden lagreVekt() til å

ta hensyn til potensielt feil registrering.

4. Du åpner filen som har klassen Person, og lokaliserer metoden lagreVekt(). Du legger

til en If-test inne i den, og vips, så har du fikset alle fremtidige feiltastinger.

5. Det fine med denne fiksen, er at du ikke trenger å endre noe annet sted enn i metoden.

Der metoden kalles fra (i ulike knapper i ulike forms) har en hele tiden antatt at ting

fungerer, uten å bry seg med detaljene i koden bak klassens metode.

Det er nettopp dette OOP handler om – å skjule detaljene. Dersom du fikser detaljene, så skal

det helst ikke gi konsekvenser for resten av programmet der klassen instansieres i form av

objekter. Du får altså økt fleksibilitet ved å la metoder sette verdiene i objektvariablene, i

stedet for å sette verdiene direkte ved å la objektvariablene være offentlige (Public).

10.3. Mulig tilnærming nr 2 – Konstruktører

Det er vanlig å bruke konstruktører for å innkapsle objektvariablene. Konstruktører gjør det

enkelt for oss å opprette et nytt objekt av en klasse (instans) og fylle dette objektet med

innhold på samme tid. Det er mulig å ha flere konstruktører for hver klasse. La oss se

nærmere på hva en konstruktør er, og motivasjonen bak.

10.3.1. Hva skjer når vi lager et nytt objekt?

Når vi skal lage et nytt objekt, bruker vi kodeordet New. Vi kan for eksempel skrive slik:

Dim elisabeth as Person

elisabeth = New Person

I første setning lager vi en liten boks i minnet som kan inneholde adresen til et objekt av type

Person. I andre setning lager vi et nytt objekt, og lagrer referansen til dette objektet i ”boksen”

som heter elisabeth. I stedet for å si at elisabeth nå er ”boksen med referansen som

henviser til objektet elisabeth”, sier vi kort og godt at elisabeth er ”objektet elisabeth”.

Det er mye enklere å snakke om objekter direkte, selv om det egentlig bare er en referanse til

objektet vi snakker om. Den øverste delen av Figur 7 viser et objekt slik vi normalt tenker på

det, mens den nederste delen viser hvordan dette objektet egentlig er representert i minnet i

Page 11: Objektorientering 2

Objektorientering i VB – videregående side 11 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

maskinen: Boksen som heter elisabeth (og som vi for enkelhetsskyld kaller objektet

elisabeth) har en verdi (referanse) som viser til det stedet i minnet hvor objektet befinner seg.

Figur 7: Objektet elisabeth slik vi kan visualisere oss det (gul figur, øverst) og slik det faktisk representeres inne i maskinen (blå, nederst). 8F6H4003 er adressen til det stedet i minnet hvor objektet ligger lagret.

Når vi oppretter et objekt får vi en kopi av den tilhørende klassen. I Figur 7 vises hvordan et

nytt objekt har de tre objektvariablene vekt, navn og hoyde, men at disse mangler innhold.

Det neste logiske steget er som regel å fylle objektet med innhold. Veldig ofte er nettopp dette

steg 2 noe vi ønsker å gjøre rett etter å ha opprettet objektet.

Kodeordet New kan brukes til å lage et objekt, og så kan vi for eksempel gi objektvariablene

verdier ved å kalle opp respektive metoder. Hva om vi kunne slå sammen disse to

operasjonene til én?

10.3.2. Konstruktører lager og fyller objektet på en gang

Når vi lager et objekt, så kan vi si at vi konstruerer objektet (engelsk: to construct an object).

Innen OOP har vi en spesiell type metode som heter konstruktør (engelsk: constructor).

Denne har i Visual Basic alltid navnet New, og kan deklareres slik i klassen vår:

Public Class Person

Private navn As String 'objektvariablene er kun tilgjengelige

Private vekt As Double 'internt i denne klassen

Private hoyde As Double 'siden de er deklarert som Private

'Her er en Constructor for å registrere en ny person

Public Sub New(ByVal etNavn As String, _

ByVal enVekt As Double, _

ByVal enHoyde As Double)

navn = etNavn

vekt = enVekt

hoyde = enHoyde

End Sub

Page 12: Objektorientering 2

Objektorientering i VB – videregående side 12 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Public Function finnBMI() As Double 'Regner her ut body mass index

Dim meter As Double

meter = hoyde / 100 'fordi vi skal regne i antall meter, ikke i cm

Return vekt/(meter*meter) 'parentesene regnes ut først

End Function

End Class

Konstruktøren er deklarert som Public, og den kan dermed kalles utenfor klassen. Siden

konsturktøren befinner seg inne i klassen, har den tilgang til alle objektvariablene som er

deklarert med Private. La oss se på bruken av konstruktøren før vi forklarer fullstendig

ferdig :

Private Sub Button1_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button1.Click

'Lager et objekt av type Person

Dim bmi As Double

Dim alex As Person

alex = New Person("Aleksander", 100, 200)

'Skriver ut verdien i objektvariabelen vekt vha Property Vekten

bmi = alex.finnBMI()

MsgBox("BMI-en er: " & bmi)

End Sub

Vi lager et objekt (alex) og setter:

alex = New Person("Aleksander", 100, 200)

Siden vi nå har en konstruktør for klassen som krever 3 argumenter, angir vi 3

argumentverdier i dette kallet. Dermed sendes det 3 argumenter inn til konstruktøren som

definert med New i klassen Person. Se nå tilbake på koden for konstruktøren, og du ser at

det som mottas heter henholdsvis etNavn, enVekt og enHoyde. Disse har nå

henholdsvis verdiene ”Aleksander”, 100 og 200. For å få ”Aleksander” inn i objektvariabelen

navn, skriver vi bare

navn = etNavn

inne i konstruktøren. Tilsvarende fylles de andre objektvariablene med riktige verdier. Nå har

vi i praksis et objekt som ser slik ut:

Figur 8: Etter at konstruktøren er benyttet, har objektet fått en rekke verdier.

10.3.3. En enda kortere syntaks

Det er mulig å skrive enda mer kompakt når vi lager objekter, enn å måtte bruke to linjer. I

stedet for:

Dim alex As Person

Page 13: Objektorientering 2

Objektorientering i VB – videregående side 13 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

alex = New Person("Aleksander", 100, 200)

kan vi skrive

Dim alex As New Person("Aleksander", 100, 200)

Dermed er det mulig å lage virtuelle utgaver av alle sine slektninger på kort tid, som vist i

Button2_Click her:

Private Sub Button2_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button2.Click

Dim alex As New Person("Aleksander", 100, 200)

Dim jeppe As New Person("Jens Peder", 78, 190)

Dim kanin As New Person("Kari Nina", 52, 167)

Dim ole As New Person("Ole Bernt Kånrad", 124.78, 197.50)

Dim berith As New Person("Berit Hjørdis", 60.25, 170)

Dim leffen As New Person("Leif Espen", 59, 156)

End Sub

Vi kunne nå funnet BMI på hver enkelt av disse, hvis ønskelig. Du ser at ved bruk av

konstruktører får vi laget objekter og fylt disse med innhold på en rask måte. Dessuten sikrer

vi oss at vi ikke glemmer å registrere objektvariablene. Konstruktører er bra å bruke.

10.3.4. Overloading

Helt til slutt nevnes et begrep som heter overloading (på engelsk). Du har tidligere sett at

metoder kan ha så mange argumenter du selv måtte ønske. Nå har vi nettopp laget en

konstruktør som fyller inn navn, vekt og høyde på en person. Hva om vi ønsker å lage et

objekt som bare har noen standardverdier, for eksempel Ola Nordmann som navn, 85 kg som

vekt og 180 som høyde? Vi kan enkelt lage en konstruktør som gjør dette:

Public Sub New()

navn = "Ola Nordmann"

vekt = 85

hoyde = 180

End Sub

Det fine er at denne konstruktøren kan leve side om side med den første konstruktøren vi

lagde. Vi kan altså ha flere konstruktører i en og samme klasse! Dette er en fin mulighet, og

det øker fleksibiliteten.

Figur 9 og Figur 10 viser eksempel på opprettelse av et nytt objekt (i for eksempel

Button1_Click) basert på klassen Person. I det vi skriver Person( hjelper

utviklingsmiljøet oss og avslører at det fins to tilgjengelige konstruktører. Disse vises i form

av en liste, og vi kan se argumentene og datatypene som forventes for hver konstruktør.

Figur 9: Utviklingsmiljøet hjelper oss og antyder at den første konstruktøren krever tre argumenter.

Page 14: Objektorientering 2

Objektorientering i VB – videregående side 14 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Figur 10: Utviklingsmiljøet viser den andre konstruktøren når vi trykker pil ned. Den andre krever ingen argumenter.

Det er vanlig at ferdiglagde .NET-klasser har mange konstruktører som en kan velge mellom.

Det er alltid lurt å lese argument-listen for å få en indikasjon av hva som kan gjøres.

Begge formene er mulige å bruke:

Dim svend as New Person("Svend", 88, 196)

Dim ola as New Person()

Som følge av den første linjen, opprettes objektet svend, og det får objektvariablene fylt med

”Svend”, 88 og 196. Den andre linjen lager et objekt som heter ola, og dette får verdiene ”Ola

Nordmann”, 85 og 180. Dette fenomenet – at vi kan ha potensielt mange konstruktører –

gjelder mer generelt også. Det er nemlig mulig å lage metoder som har samme navn, så lenge

antall argumenter varierer. Vi skal ikke gå nærmere inn på dette.

Et lite apropos: Egentlig trenger en ikke skrive parenteser etter Person i den siste linjen. VB

tillater både med og uten parentes dersom argumentlisten er tom.

10.4. Mulig tilnærming nr 3 – bruk av Property

Det er flott å kunne bruke metoder for å lagre informasjon i en objektvariabel, og for å hente

ut informasjon fra en objektvariabel. Det er derimot litt mer tungvindt å måtte kalle en metode

enn å kunne bruke syntaksen som vist aller først i denne leksjonen:

knut.vekt = 76

Den gode nyheten er at det faktisk er mulig å skrive på denne måten, og samtidig beholde

objektvariablene med modifikatoren Private.

10.4.1. Property brukes primært til å hente og endre verdi i objektvariabler

Det fins en spesiell konstruksjon som vi kaller Property som gjør det mulig å fortsatt å ha

objektvariabler som er beskyttet inne i klassen, og samtidig tilby en enkel syntaks for å endre

eller lese verdiene. En Property er en slags metode, men en metode med en veldig spesiell

syntaks. Den brukes i de fleste objektorienterte programmeringsspråk. Strukturen ser slik ut

og skrives inn i klassen:

Public Class Person

Private navn As String 'objektvariablene er kun tilgjengelige

Private vekt As Double 'internt i denne klassen

Private hoyde As Double 'siden de er deklarert som Private

Public Property Vekten() As Double

Get

'Kode du måtte ønske her, typisk

Return vekt

End Get

Set(ByVal value As Double)

'Kode du måtte ønske her, typisk

vekt = value

End Set

Page 15: Objektorientering 2

Objektorientering i VB – videregående side 15 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

End Property

'Eventuelt flere Property-strukturer og metoder her...

'...

'...

End Class

En Property kan brukes i stedet for metoder som for eksempel lagreHoyde() og hentHoyde().

Det er nødvendig å se på bruken av Property-en før vi kan forklare forskjellen på Get og Set.

Gitt følgende kode i Button1_Click:

'Demonstrerer bruk av Property

Private Sub Button1_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button1.Click

'Lager et objekt av type Person

Dim jens As Person

jens = New Person

'Registrerer en verdi i objektvariabelen vekt vha Property Vekten

jens.Vekten = 97

'Skriver ut verdien i objektvariabelen vekt vha Property Vekten

MsgBox(jens.Vekten)

End Sub

10.4.2. Forklaring til Get og Set

Det som står mellom Get og End Get aktiveres ganske enkelt når vi i knappen

Button1_Click (eller liknende) skriver

MsgBox(jens.Vekten)

Når vi skriver på syntaksen objekt.Propertynavn, så ønsker vi typisk å hente ut

verdien. Siden Property-strukturen Vekten() egentlig er en slags metode, kan vi bruke

kodeordet Return for å returnere en verdi. Det kan være forvirrende at Property-en ikke

skrives på samme måte som vanlige funksjoner og metoder når den kalles opp, men det er noe

du bare må akseptere. Det som nå er viktig å huske på, er at objektvariabelen vekt er

deklarert som Private i klassen. Det betyr at vekt ikke kan hentes utenfor klassen, men den

kan derimot hentes av alle metoder inne i klassen. Dette inkluderer vår Property som heter

Vekten(). Dermed kan vi skrive setningen Return vekt for å sikre at når en i for

eksempel Button1_Click skriver inn MsgBox(jens.Vekten), så vil kompilatoren

aktivere objektet jens sin Property som heter Vekten() og returnere innholdet i

objektvariabelen vekt. Dermed står det i praksis MsgBox(97), slik at 97 skrives ut.

Det som står mellom Set og End Set aktiveres når vi skriver

jens.Vekten = 97

Tallet bak likhetstegnet sendes som argument til Set-delen av Property-en som heter

Vekten(), og dette argumentet blir gitt navnet value i vårt tilfelle. Vi kunne kalt det noe

annet (mer om det straks). Det vi typisk ønsker når vi skriver slik, er jo å endre

objektvariabelen vekt, slik at den får verdien 97. Derfor er det fornuftig å ha koden vekt =

value inne i Set-delen.

Merk at vi kunne hatt hvilken som helst kode inne i Get-blokken og Set-blokken. Det er mest

fornuftig å henholdsvis lese og sette (lagre) verdier i tilhørende objektvariabler, men det er

Page 16: Objektorientering 2

Objektorientering i VB – videregående side 16 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

ikke noe krav om det. En kunne også gjort mye mer, for eksempel loggført det som skjedde til

en tekstfil eller en database, en kunne foretatt feilsjekking (validering) og så videre. Som regel

er det derimot nok å bare lese/sette objektvariablene, men husk for fremtiden at mer går an.

10.4.3. Detaljer og ytterligere forklaring

Det er noen detaljer som er verdt å merke seg, som leder oss til en slags ”beste praksis” ved

bruk av Property i Visual Basic:

Det er vanlig i VB å bruke stor bokstav når en navngir en Property.

Merk at det skal være parentes etter selve navnet på en Property, for eksempel

Vekten().

I klassen Person har vi en objektvariabel som heter vekt. Det er vel og bra, men

siden vi ikke kan ha samme navngiving på to variabler, en funksjon og en variabel, en

variabel og en konstant og så videre, så må vi kalle vår Property for noe annet enn

Vekt().

Vi har valgt Vekten() som navn. Det er litt dumt. Det ville vært bedre å gjøre

motsatt: å la objektvariabelen hete vekten, og så la egenskapen (Property-en) hete

Vekt(). Da ville brukeren kunne skrive lise.Vekt = 62, noe som er mer

naturlig enn å skrive lise.Vekten = 62.

Det er ofte ønskelig å ha logiske navn på sine egenskaper/Properties. En mye brukt

konvensjon for å oppnå dette, er å la objektvariabler starte med prefikset m_, for

eksempel: m_vekt, m_navn, m_hoyde. Bokstaven ”m” står for ”member”, fordi

”objektvariabel” på engelsk gjerne kalles for ”member variable”. Noen bruker o_

som prefiks, og tenker da på ”objektvariabel”. Du velger selv om du i det hele tatt vil

bruke prefiks eller ikke. Gjør du det, så kan du i hvertfall trygt bruke logiske navn på

det du lager som Property-navn, og da blir det enklere å bruke objektet utenfor

klassen.

Det er viktig at selve Property-en er deklarert som Public. Modifikatoren angir

hvor noe skal være synlig, og Public gjør det mulig for Property-en å brukes

utenfor klassen. Det er som regel det vi ønsker.

Vi bruker samme datatype i vår Property som på objektvariabelen som skal behandles.

10.4.4. Hva har en skarve TextBox og en Label å gjøre med en Aha-opplevelse?

Den observante leser har allerede fått et deja vû, men har kanskje ikke lokalisert dette enda.

Vi skal nå gjøre et VIKTIG EKSPERIMENT. Tenk først litt over måten å skrive disse

setningene på:

Dim kari as New Person

Dim ut as String

kari.Vekten = 62

ut = "Kari veier " & kari.Vekten & " kilo"

MsgBox(ut)

Sammenlikn så koden over, med følgende kode:

Dim antallKg as Double

Page 17: Objektorientering 2

Objektorientering i VB – videregående side 17 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Label1.Text = 62

ut = "Kari veier " & Label1.Text & " kilo"

MsgBox(ut)

Denne koden kunne du ha laget nokså tidlig i din karriere som VB-programmerer. Ser du

likheten? TextBox1.Text, Label1.Text og så videre har samme skrivemåte som vår

bruk av Property. Det er fordi TextBox1 bare er et konkret objekt som er opprettet basert

på klassen TextBox, og denne klassen har tilfeldigvis en Property som heter Text().

Derfor kan vi skrive slik.

Aha! Det er altså sånn det henger sammen! Alle objekter i grensesnittet er nettopp det:

objekter, og da har de selvsagt metoder og Properties (gjerne kalt egenskaper på norsk).

De løse trådene begynner nå å nøste seg sammen i synk med at vi ser nærmere på

mekanismene bak objektorientering. Hvis dette var uklart, så dvel litt ved eksempelet og les

det på nytt på et senere tidspunkt.

Figur 11: Egenskapene (Properties) til en bestemt Label til venstre og en TextBox til høyre. Utviklingsmiljøet lar oss på en enkel måte lese verdiene og endre disse.

Legg merke til hvordan en Label kan ha mange egenskaper som kan endres (se Figur 11) i

utviklingsmiljøet. Egenskapene kontrollerer hvordan objektet oppfører seg. Det fine er at en

også kan endre disse egenskapene i koden. Det er faktisk det som skjer bak kulissene når du

endrer noe i utviklingsmiljøet (ala Figur 11) ! Dette blir kanskje Aha-opplevelse nummer to

for noen. Utviklingsmiljøet er altså bare et grensesnitt inn mot koden, og det er laget for at vi

på en enklere, mer visuell måte, skal kunne fylle objektene våre med innhold!

Dersom du i koden vil gjøre TextBox1 usynlig, er det bare å skrive:

TextBox1.Visible = False

Det som da egentlig skjer, er at Property-en Visible() sin Set-del i klassen som definerer

tekstbokser, utføres. Du kan tilsvarende teste på om en tekstboks er synlig ved å skrive for

eksempel:

If TextBox1.Visible Then

MsgBox("Du kan nå skrive inn noe i tekstboksen, kjære bruker")

Else

MsgBox("Boksen er usynlig, din uheldiggris")

End If

!

Page 18: Objektorientering 2

Objektorientering i VB – videregående side 18 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Nå er det Get-delen som aktiveres. Den returnerer enten True eller False, avhengig av om

tekstboksen er synlig eller ikke. Hvis den returnerer True, så står det i praksis If True

Then... og da vil meldingsboksen vises med beskjed om at brukeren kan skrive inn noe i

tekstfeltet. Hvis den returnerer False, så står det i praksis If False Then ... og da

blir ikke brukeren like oppmuntret.

10.4.5. En siste Aha-opplevelse

Vi gir oss ikke, nå skal vi helt til bunns i alle hemmeligheter. ”Enter Aha-experience number

three”: Når du lager et program, så starter du gjerne med en Form. Du legger så til en knapp,

du drar litt i hjørnene for å få den større, du endrer kanskje farge og en rekke andre ting. Du

lager så en listeboks, og er fornøyd. Det tar 30 sekunder. Resultatet vises i Figur 12.

Figur 12: En ”form” med en ”button” og en ”listbox” laget på 30 sekunder i utviklingsmiljøet...

Du kunne også programmert alt dette, for hånd. Dersom du i Solution Explorer klikker på det

andre ikonet, så får du se noen ”skjulte” filer. Der finner du blant annet all den koden som

representerer Form1.

Ved å se på koden i filen Form1.Designer.vb, ser vi følgende auto-genererte kode:

Me.Button1 = New System.Windows.Forms.Button

Me.ListBox1 = New System.Windows.Forms.ListBox

Me.SuspendLayout()

'

'Button1

'

Me.Button1.Font = New System.Drawing.Font("Microsoft Sans Serif", 20.0!,

System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0,

Byte))

Me.Button1.ForeColor = System.Drawing.Color.RoyalBlue

Me.Button1.Location = New System.Drawing.Point(22, 12)

Me.Button1.Name = "Button1"

Me.Button1.Size = New System.Drawing.Size(174, 116)

Me.Button1.TabIndex = 0

Me.Button1.Text = "Min superknapp!"

Me.Button1.UseVisualStyleBackColor = True

'

'ListBox1

'

Me.ListBox1.FormattingEnabled = True

Me.ListBox1.Location = New System.Drawing.Point(230, 33)

Page 19: Objektorientering 2

Objektorientering i VB – videregående side 19 av 19

Opphavsrett: Forfatter og Stiftelsen TISIP

Me.ListBox1.Name = "ListBox1"

Me.ListBox1.Size = New System.Drawing.Size(120, 95)

Me.ListBox1.TabIndex = 1

'

'Form1

'

Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)

Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font

Me.ClientSize = New System.Drawing.Size(393, 166)

Me.Controls.Add(Me.ListBox1)

Me.Controls.Add(Me.Button1)

Me.Name = "Form1"

Me.Text = "Form1"

Me.ResumeLayout(False)

Dette er altså koden som skal til for å lage grensesnittet i Figur 12! Aha, aha, aha! I koden ser

du noen setninger og uttrykk i fet skrift. Det er for å tydeliggjøre at det som er formattert i

grensesnittet, i bunn og grunn representeres med kode. Listeboksen er dradd noe til høyre på

Form1, og den har en viss størrelse. Dette er kodet vha egenskaper som .Location og .Size. Vi

ser at først opprettes en knapp ved hjelp av koden

Me.Button1 = New System.Windows.Forms.Button

Knappen får en skrifttype, nemlig Microsoft Sans Serif på 20 punkter, og fargen settes til blå:

Me.Button1.Font = New System.Drawing.Font("Microsoft Sans Serif", 20.0! '.......

Me.Button1.ForeColor = System.Drawing.Color.RoyalBlue

Knappen får et navn, og en tekst som vises for brukeren:

Me.Button1.Name = "Button1"

Me.Button1.Text = "Min superknapp!"

Tenk nå over hvor tidkrevende det ville vært å skrive denne koden selv. Du kan selvsagt gjøre

det, hvis du vil, og du kan skrive koden i Notisblokk, hvis du vil, men det tar garantert ikke 30

sekunder. Aha.