Mer om klasser

Sven-Olof Nyström
OOP med Java våren -25
Informationsteknologi
Uppsala Universitet

Detta avsnitt berättar mer om klasser i Java och beskriver koncept som klassvariabler, klassmetoder, inkapsling, synlighet, paket, slutgiltiga klasser och metoder. Det här är sånt som du bör vara bekant med. Detaljerna är inte superviktiga, men om du stöter på begreppen i text eller i kod bör du känna igen dem.

Vad vi vet om objekt och klasser

Frågor om klasser

Några frågeställningar:

Klassvariabler

Exempel:

static int x;

En klassvariabel

Klassvariabler, exempel

Den statiska variabeln counter håller reda på hur många objekt som skapats i klassen X.

class X {
   static int counter = 0;

   int number;

   X () {
      counter = counter + 1;
      number = counter;
   }
}

Klassvariabler, testkörning

X a = new X();
X b = new X();
X c = new X();

System.out.println(c.number);

Variabeln c får ordningsnummer 3.

Den statiska variabeln X.counter lagrar antal objekt i klassen.

När kan det passa med klassvariabler?

Ett exempel ur Skansholms bok (kapitel 3):

Anta att vi har en klass Konto med

Här har alla konton samma räntesats, men varje konto har sitt eget saldo. (Hur skulle det annars se ut?)

Klassmetoder, exempel

Ett exempel med en klassmetod.

Vad beräknar denna metod?

class F {
   static double m(double x, double y) {
      return (x + y) / 2;
   }
}

Anropet F.m(4.2, 9) ger resultatet 6.6.

Klassmetoder

Jämför

Notera: klassmetoder och klassvariabler gör det lätt att skriva program som inte följer principerna för objektorienterad programmering. Om man vill lära sig OOP är det lämpligt att till en början undvika static.

Inkapsling och synlighet, modell

public class V {
   private int x;

   public void setX(int x1) {
      x = x1;
   }

   public int getX() {
      return x;
   }
}

Vi kan inte komma åt instansvariabeln x direkt:

V v; v.x = ...

är inte tillåtet.

Men med metoderna setX() och getX() kan värdet på x läsas och skrivas.

En instansvariabel, klassvariabel eller metod kan deklareras private. Då kan variabeln eller metoden bara användas i klassen.

Alternativet, public är default (nästan).

Synlighet, rekommendation

Lite om paket i Java

Motiv: Paketbegreppet ger en slags modularisering av större program. Det är ofta lämpligt att samla relaterade klasser i ett paket. Paket gör det möjligt att undvika namnkonflikt om man av nån anledning definierar olika klasser med samma namn. Klasser i ett paket kan dela definitioner som ej är synliga utåt.

(Paket kommer inte att spela någon större roll i denna kurs, men ni bör vara bekanta med begreppet. Ni kommer att komma i kontakt med paket när ni använder olika bibliotek.)

Man talar om att en viss klass ska ingå i ett visst paket med en deklaration

package mittPaket;

som ska stå först i filen.

Precis som en klass i Java (normalt) definieras i en fil med samma namn, måste alla .class-filer som ingår i ett visst paket finnas i en mapp (directory) med samma namn.

Paket i paket

Ett paket kan innehålla andra paket. Exempel:

mittPaket.ettAnnatPaket

Klassfilerna till paketet ettAnnatPaket ska ligga i mappen ettAnnatPaket som i sin tur ska finnas i mappen mittPaket.

Åtkomst i ett paket

För att komma åt en klass i ett visst paket kan man använda klassens fullständiga namn, tex

mittPaket.KlassNamn

eller

mittPaket.ettAnnatPaket.KlassNamn

(Java tillåter att det finns en klass med namnet KlassNamn i båda paketen.)

Import

Man kan importera en viss klass eller ett visst paket, tex

import mittPaket.KlassNamn eller

import mittPaket.ettAnnatPaket.KlassNamn

För att importera alla klasser i ett visst paket skriver man:

import mittPaket.*; eller

import mittPaket.ettAnnatPaket.*;

Kollision

Om man importerar två klasser med samma korta namn (och använder detta namn) ger kompilatorn ett felmeddelande.

Exempel:

import java.util.*;
import javax.swing.*;

class Foo {

    Timer t;

}

Både java.util och javax.swing (två paket) definierar en klass Timer.

Konflikten kan lösas genom att man explicit anger vilken klass man vill använda. Lägg till följande deklaration:

import javax.swing.Timer;

så kompilerar programmet.

Att leta filer

Hur hittar kompilatorn källkodsfilerna vid kompilering?

Vid kompilering från kommandoraden gäller:

Integrerade utvecklingsmiljöer (IDE) brukar lägga källkodsfiler och objektkodsfiler på olika platser i filsystemet.

En systemvariabel CLASSPATH kan användas för att styra var program som kompilatorn (javac) och run-time systemet (java) placerar och söker efter .java- och .class-filer.

(Vanligtvis behöver du inte tänka så mycket på de här sakerna, men om du skulle stöta på problem rekommenderar jag relevant dokumentation, till exempel http://docs.oracle.com/javase/tutorial/java/package/managingfiles.html)

Paket—synlighet

Om man inte anger synlighet för ett namn kommer namnet att vara synligt för andra klasser inom samma paket.

Reglerna för synlighet sammanfattas i denna tabell:

public "paket" protected private
Klassen ja ja ja ja
Annan klass (samma paket) ja ja ja nej
Subklass (annat paket) ja nej ja nej
Annan klass (i annat paket) ja nej nej nej

Sammanfattning:

Notera att protected lite paradoxalt ger mindre skydd än om man inte anger någon synlighet. protected används sällan.

Konstanter

Konstanter deklareras med nyckelordet final.

class Person {
    int ålder;
    final String namn;

    Person (String n, int å) {
        ålder = å;
        namn = n;
    }
}

En instansvariabel som deklarerats med final får ett värde när objektet skapas. Detta värde kan inte modifieras efteråt.

Även klassvariabler kan deklareras static. Här är tex definitionen av pi i java.lang.Math:

public static final double PI = 3.14159265358979323846;

Slutgiltiga klasser och metoder

Vi kan deklarera klasser och metoder med nyckelordet final.

Motivering: Ger effektivare kod. Gör det möjligt för en konstruktör av en klass att styra hur andra bygger vidare på klassen.