UML Class diagram¶
Het uittekenen van onze klassenmodellen doen we met ‘blokken’ en ‘pijltjes’ zoals bij zoveel diagrammen. Je hebt misschien al eens gezien hoe je dit doet voor een datamodel of voor een functiestroomdiagram. Al deze modellen kunnen we weergeven op dezelfde manier, zodat we met elkaar makkelijker kunnen praten over die modellen en dezelfde taal daarin spreken. Hiervoor is een algemene manier van schrijven en tekenen bedacht die heet “Unified Modeling Language”. Voor klassenmodellen is dit toegepast met speciale symbolen die hier belangrijk zijn. Dan kunnen we een “Class model” maken.
graph BT
UML[UML Diagram]
Structural
Behavioral
Interaction
Class
Object
Component
CompositeStructure
Deployment
Package
UseCase
Activity
StateMachine
Communication
InteractionOverview
Sequence
Timing
Structural --> UML
Behavioral --> UML
Interaction --> Behavioral
Class --> Structural
Object --> Structural
Component --> Structural
CompositeStructure --> Structural
Deployment --> Structural
Package --> Structural
UseCase --> Behavioral
Activity --> Behavioral
StateMachine --> Behavioral
Communication --> Interaction
InteractionOverview --> Interaction
Sequence --> Interaction
Timing --> Interaction
Een “class diagram” is een soort van “diagram” maar dan dus specifiek voor klassebeschrijvingen. Bij programmeren kunnen we ook de “State machine diagram” gebruiken om te bepalen hoe een programma zou moeten werken, als onderdeel van het ontwerp.
Een class beschrijven met UML¶
Met behulp van UML kunnen we dus ook onze klassen op een uniforme manier definiëren. Het voorbeeld staat hieronder. De naam staat altijd boven, gecentreerd, en iets groter en dikker. De eigenschappen volgen daarna. Voor elke eigenschap definiëren we ook het datatype. Als laatste beschrijven we de methodes. Daarin zie je de naam van de methode en de benodigde argumenten. Het resultaattype wordt niet getoond omdat dit altijd hetzelfde is; een nieuwe vorm van het object (bij setters) of het datatype van het opgevraagde (bij getters).
classDiagram
class BankAccount{
owner: String
balance: Dollar = 0
deposit(amount: Dollar)
withdraw(amount: Dollar)
calculateInterest()
}
Access modifiers¶
In UML kunnen we ook aangeven of een eigenschap of methode publiek, privaat of beschermd is. Dit doen we met een plus, min of hekje voor de naam van de eigenschap of methode.
classDiagram
class BankAccount{
+owner: String
-balance: Dollar = 0
+deposit(amount: Dollar)
+withdraw(amount: Dollar)
-calculateInterest()
}
In het bovenstaande voorbeeld is de eigenschap owner
publiek, en de eigenschap balance
privaat. De methodes deposit
en withdraw
zijn publiek, en de methode calculateInterest
is privaat.
Static¶
In UML kunnen we ook aangeven of een eigenschap of methode statisch is. Dit doen we met een onderstreepte naam.
classDiagram
class BankAccount{
+owner: String
-balance: Dollar = 0
+deposit(amount: Dollar)
+withdraw(amount: Dollar)
-calculateInterest()
numberOfAccounts$: int $
}
In het bovenstaande voorbeeld is de eigenschap numberOfAccounts
statisch.
Relaties tussen klassen¶
In UML kunnen we ook aangeven hoe klassen met elkaar samenwerken. Dit doen we met lijnen tussen de klassen. De lijnen hebben een bepaalde betekenis.
Association¶
Een association is een relatie tussen twee klassen. Deze relatie is altijd bidirectioneel. Dit betekent dat beide klassen elkaar kennen. De lijn heeft een pijlpunt aan beide kanten.
classDiagram
class BankAccount{
+owner: Owner
-balance: Dollar = 0
+deposit(amount: Dollar)
+withdraw(amount: Dollar)
-calculateInterest()
numberOfAccounts: int $
}
class Owner{
+name: String
-address: String
+phoneNumber: String
+getAddress()
}
BankAccount --> Owner
In het bovenstaande voorbeeld is de relatie tussen BankAccount
en Owner
een association.
Aggregation¶
Een aggregation is een relatie tussen twee klassen. Deze relatie is altijd bidirectioneel. Dit betekent dat beide klassen elkaar kennen. De lijn heeft een leeg ruitje aan de kant van de klasse die de andere klasse bevat.
classDiagram
class BankAccount{
+owner: Owner
-balance: Dollar = 0
+deposit(amount: Dollar)
+withdraw(amount: Dollar)
-calculateInterest()
numberOfAccounts: int $
}
class Owner{
+name: String
-address: String
+phoneNumber: String
+getAddress()
}
BankAccount o-- Owner
In het bovenstaande voorbeeld is de relatie tussen BankAccount
en Owner
een aggregation. De BankAccount
bevat een Owner
. De Owner
kan bestaan zonder BankAccount
.
Composition¶
Een composition is een relatie tussen twee klassen. Deze relatie is altijd bidirectioneel. Dit betekent dat beide klassen elkaar kennen. De lijn heeft een gevuld ruitje aan de kant van de klasse die de andere klasse bevat.
classDiagram
class BankAccount{
-balance: Dollar = 0
+deposit(amount: Dollar)
+withdraw(amount: Dollar)
-calculateInterest()
numberOfAccounts: int $
}
class Owner{
-bankAccount: BankAccount
+name: String
-address: String
+phoneNumber: String
+getAddress()
+getBankAccount()
}
BankAccount --* Owner
In het bovenstaande voorbeeld is de relatie tussen BankAccount
en Owner
een composition. De BankAccount
bevat een Owner
. De BankAccount
kan niet bestaan zonder Owner
.
Inheritance¶
Een inheritance is een relatie tussen twee klassen. Deze relatie is altijd unidirectioneel. Dit betekent dat de ene klasse de andere klasse kent, maar niet andersom. De lijn heeft een leeg driehoekje aan de kant van de klasse die de andere klasse erft.
classDiagram
class BankAccount{
-balance: Dollar = 0
+deposit(amount: Dollar)
+withdraw(amount: Dollar)
-calculateInterest()
numberOfAccounts: int $
}
class SavingsAccount{
-interestRate: double
+calculateInterest()
}
BankAccount <|-- SavingsAccount
In het bovenstaande voorbeeld is de relatie tussen BankAccount
en SavingsAccount
een inheritance. De SavingsAccount
erft van BankAccount
. De BankAccount
kent de SavingsAccount
niet.