Programmering nivå 2

Kap 3.5 – UML för objektmodeller

Planera objektorienterade program med klassdiagram, attribut, metoder och relationer.

Mål med lektionen

När du har arbetat klart med denna lektion ska du:

  • Förstå vad ett UML-klassdiagram är och hur det används för att planera programstruktur.
  • Kunna tolka enkla UML-diagram och koppla dem till kod.
  • Kunna skapa egna UML-klassdiagram med attribut, metoder och relationer.

Så här lär du dig bäst

UML är inte kod. Det är ett visuellt språk för att strukturera din kod innan du skriver den. Studera exemplen noggrant och försök sedan att omvandla UML till kod, eller kod till UML. UML hjälper dig att få överblick och planera logiskt.

Centrala begrepp

  • UML: ett standardiserat sätt att rita upp system och programstruktur.
  • Klassdiagram: en UML-modell som visar klasser, attribut, metoder och relationer.
  • Attribut eller fält: variabler som hör till en klass eller ett objekt, till exempel self.name eller self.balance.
  • Metoder: funktioner som hör till en klass eller ett objekt.
  • Association: en relation mellan två klasser.
  • Arv: en relation där en klass ärver från en annan.

UML för objektmodeller

Ett klassdiagram visar ofta varje klass som en ruta med tre delar:

  1. klassens namn,
  2. attribut, alltså fält eller variabler,
  3. metoder, alltså funktioner eller beteenden.
Vanliga UML-symboler i yEd Live.
Vanliga UML-symboler i yEd Live.

De vanligaste symbolerna används så här:

  • Class: en vanlig klass. Den används för klasser som du kan skapa objekt av.
  • Interface: en beskrivning av metoder som andra klasser ska följa. Du behöver inte använda interface i de första exemplen.
  • Abstract: en abstrakt klass. Den används som gemensam grund för andra klasser och är mer avancerad.
  • Enkel pil: i den här kursen använder du bara vanlig pil, -->, för relationer mellan klasser.

Bilden visar flera UML-symboler, men i den här kursen ska du bara använda den enkla pilen -->. Skriv en kort etikett efter kolon, till exempel inherits, has eller owns. has betyder "har" och owns betyder "äger" eller "ansvarar för".

Exempel: klassdiagram för Dog

classDiagram
    class Dog {
        -string name
        -int age
        +bark() void
        +haveBirthday() void
    }

Samma klass kan skrivas så här i Python. Attributen i diagrammet motsvarar self._name och self._age i koden, och metoderna motsvarar funktionerna som ligger inne i klassen.

class Dog:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def bark(self):
        print("Voff!")

    def have_birthday(self):
        self._age += 1


dog = Dog("Fido", 3)
dog.bark()
dog.have_birthday()

Symbolerna betyder:

  • + betyder publik.
  • - betyder privat.
  • # betyder skyddad, alltså protected.
  • Typen, till exempel string eller int, visar vilken datatyp attributet har.

I UML skrivs metodnamn ofta som haveBirthday() eller printInfo(). I Python använder man oftast snake_case, till exempel have_birthday() och print_info().

Relationer mellan klasser: arv

Här visar den enkla pilen att Dog ärver från Animal. Etiketten inherits förklarar relationen.

classDiagram
    Dog --> Animal : inherits

    class Animal {
        +speak() void
    }

    class Dog {
        +bark() void
        +speak() void
    }

I Python syns arvet genom parentesen efter klassnamnet: class Dog(Animal). Då kan Dog använda och skriva över metoder från Animal.

class Animal:
    def speak(self):
        print("Djuret gör ett ljud.")


class Dog(Animal):
    def bark(self):
        print("Voff!")

    def speak(self):
        print("Hunden skäller.")


dog = Dog()
dog.speak()
dog.bark()

Association mellan klasser

Association betyder att två klasser har en koppling. En skola kan till exempel ha flera studenter.

classDiagram
    School --> Student : has

    class Student {
        -string name
        -int age
        +printInfo() void
    }

    class School {
        -string name
        -string city
        -list students
        +addStudent(student) void
    }

I koden visas associationen genom att ett School-objekt sparar Student-objekt i en lista.

class Student:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def print_info(self):
        print(f"{self._name}, {self._age} år")


class School:
    def __init__(self, name, city):
        self._name = name
        self._city = city
        self._students = []

    def add_student(self, student):
        self._students.append(student)


student = Student("Anna", 17)
school = School("Pauliskolan", "Malmö")
school.add_student(student)

Exempel: bankapplikation

En enkel bankmodell kan innehålla kunder, konton och en bank. Diagrammet visar att en bank har kunder och att en kund kan ha konton.

classDiagram
    Bank --> Customer : has
    Customer --> Account : owns

    class Bank {
        -string name
        -list customers
        +addCustomer(customer) void
        +findCustomer(name) Customer
    }

    class Customer {
        -string name
        -string customerId
        -list accounts
        +addAccount(account) void
        +getAccounts() list
        +getName() string
    }

    class Account {
        -string accountNumber
        -float balance
        +deposit(amount) void
        +withdraw(amount) bool
        +getBalance() float
    }

Här är en förenklad kodversion av samma modell. Lägg märke till att listorna visar relationerna: banken har kunder och kunden har konton.

class Account:
    def __init__(self, account_number, balance):
        self._account_number = account_number
        self._balance = balance

    def deposit(self, amount):
        if amount > 0:
            self._balance += amount

    def withdraw(self, amount):
        if 0 < amount <= self._balance:
            self._balance -= amount
            return True
        return False

    def get_balance(self):
        return self._balance


class Customer:
    def __init__(self, name, customer_id):
        self._name = name
        self._customer_id = customer_id
        self._accounts = []

    def add_account(self, account):
        self._accounts.append(account)

    def get_accounts(self):
        return self._accounts

    def get_name(self):
        return self._name


class Bank:
    def __init__(self, name):
        self._name = name
        self._customers = []

    def add_customer(self, customer):
        self._customers.append(customer)

    def find_customer(self, name):
        for customer in self._customers:
            if customer.get_name() == name:
                return customer
        return None


bank = Bank("Skolbanken")
customer = Customer("Erik", "C001")
account = Account("1001", 500)

customer.add_account(account)
bank.add_customer(customer)

Öva själv

Övning 1: Läs ett klassdiagram

Studera UML-diagrammet för Dog tidigare i kapitlet. Skriv ner klassens namn, attribut, metoder, datatyper och synlighet. Skriv därefter motsvarande Python-klass och skapa ett objekt som använder båda metoderna.

Fundera: Vilka delar av UML-diagrammet motsvarar self-attributen?

När du har försökt själv: visa lösningsförslaget till övning 1 på GitHub.

Övning 2: Rita klassen Student

Planera klassen Student med attributen name och points samt metoderna add_points(amount) och print_info(). Rita ett UML-diagram med synlighet och datatyper och skriv sedan Python-koden.

Fundera: Varför står parametrar inne i metodens parenteser men attribut i diagrammets mittdel?

När du har försökt själv: visa lösningsförslaget till övning 2 på GitHub.

Övning 3: Visa en association

Skapa ett UML-diagram med klasserna Team och Player. Ett lag ska ha ett namn och en lista med spelare. En spelare ska ha ett namn. Visa relationen med en enkel pil och etiketten has. Skriv sedan kod där Team kan lägga till och visa spelare.

Fundera: Var i Python-koden syns associationen?

När du har försökt själv: visa lösningsförslaget till övning 3 på GitHub.

Övning 4: Visa arv i UML

Skapa ett UML-diagram för basklassen Employee och subklassen Teacher. Båda ska ha metoden print_info(), men läraren ska även ha attributet subject. Visa arvet med en pil och skriv motsvarande Python-kod med override.

Fundera: Vilket attribut behöver bara stå i subklassen?

När du har försökt själv: visa lösningsförslaget till övning 4 på GitHub.

Övning 5: Modellera ett bibliotek

Svårare övning: Här kombinerar du flera klasser, associationer, listor och metoder.

Planera klasserna Library, Book och Member. Biblioteket ska ha listor med böcker och medlemmar. Rita klassernas attribut, metoder och associationer och skriv kod som lägger till och skriver ut böcker och medlemmar.

Fundera: Vilken klass ansvarar för samlingarna?

När du har försökt själv: visa lösningsförslaget till övning 5 på GitHub.

Övning 6: Modellera en webbutik

Svårare övning: Här planerar och kodar du ett helt objektssystem med tre relaterade klasser.

Skapa UML och Python-kod för Store, Customer och Product. Butiken ska ha produkter och kunder. Kunden ska ha en kundvagn med produkter och kunna beräkna totalsumman. Visa alla attribut, metoder och relationer innan du skriver koden.

Fundera: Vilka relationer ska märkas has och vilken kan märkas owns?

När du har försökt själv: visa lösningsförslaget till övning 6 på GitHub.

Verktyg att använda

Du kan rita UML för hand eller med digitala verktyg.

  • yEd Live - gratis webbsida där du kan rita diagram direkt i webbläsaren.

Film: yEd Live

Kort guide: rita UML i yEd Live

  1. Öppna yEd Live och välj Launch.
  2. Skapa ett nytt tomt diagram.
  3. Välj Palette -> UML för att visa UML-symbolerna.
  4. Lägg in en klassruta för varje klass, till exempel Bank, Customer och Account.
  5. Skriv klassens namn överst i rutan. Skriv attribut under namnet, till exempel - name och - balance.
  6. Skriv metoder längst ner i rutan, till exempel + deposit(amount) och + getBalance().
  7. Dra linjer mellan klasserna för att visa relationer. Exempel: Bank har kunder och Customer har konton.
  8. Använd automatisk layout om diagrammet blir rörigt. yEd Live har färdiga layouter, bland annat för UML.
  9. Spara ofta. Välj gärna GraphML om du vill kunna öppna och redigera diagrammet igen senare. Google Drive går också bra om det fungerar på din dator.
  10. Exportera diagrammet när det är klart. yEd Live kan exportera till till exempel PNG, SVG och PDF.
Menyvalet Palette och UML i yEd Live.
Välj Palette -> UML för att få fram UML-symbolerna.

yEd Live körs i webbläsaren och är gratis att använda. Enligt yWorks skickas diagramdata inte till deras servrar om du inte själv väljer molnlagring eller AI-stöd.

Sammanfattning

  • UML-klassdiagram visar klasser, attribut, metoder och relationer visuellt.
  • De hjälper dig att planera, förklara och strukturera din kod.
  • Arv, association och inkapsling kan visas grafiskt.
  • UML är ett kraftfullt analysverktyg för objektorienterad programmering.

Tillbaka till Kapitel 3