(class-diagram)=
# Class diagram

We have already introduced basic concepts of OOP in section {ref}`fundamental-concepts-oop`.

:::{wpd} class diagram
a diagram that describes the structure of a system by showing the system's classes, their attributes, methods and the relationships among objects
:::

## Class elements

Classes are blueprints for objects. They have data and methods:

::::{grid} 2
:::{grid-item-card} class diagram
```{mermaid}
classDiagram
class Plant {
    +string Name
    +string Species
    +string LookupPlantDatabase()
}
```
:::
:::{grid-item-card} class implementations
```cs
var p1 = new Plant();
p1.Name = "Kaiser";
p1.Species = "kale";

var p2 = new Plant
{
    Name = "Morten",
    Species = "Hortensia"
};
Console.WriteLine(p2.LookupPlantsDatabase());

public class Plant
{
    public string Name;
    public string Species;

    public string LookupPlantsDatabase()
    {
        return "information";
    }
}
```
`p1` and `p2` are instances of `Plant` to demonstrate how we use classes. Instances are typically not depicted in a class diagram.
:::
::::

:::{activity} Implementing the item class
:label: implementing-the-item-class
Implement the class `Item`, which has the following data and methods:

- name
- price per unit
- `string ToString()` that returns:
  
  ```text
  {name}: {price per unit} per unit
  ```
Create one instance of the item and use `ToString` to print information about the instance object.
:::

## Inheritance

Imagine we have also edible and ornamental plants. These special plants have also all properties of a `Plant`. So we save code by using *inheritance*.

:::{wpd} inheritance
:id: Inheritance_(object-oriented_programming)
mechanism of basing a class or object upon another class, retaining similar implementation
:::

::::{grid} 2
:::{grid-item-card} class diagram
```{mermaid}
classDiagram
class Plant {
    +string name
    +string species
    +string LookupPlantDatabase()
}
class Edible {
   +uint caloriesPer100g 
}
class Ornamental {
    +string color
}
Plant <|-- Edible
Plant <|-- Ornamental
```
:::
:::{grid-item-card} class implementations
```{literalinclude} ../code/inheritance.cs
:language: cs
```
`Plant` is a *base* class. Colon `a: b` means *a inherits from b*. Data fields and methods of the base class become also part of children in inheritance.
:::
::::

:::{activity} Implementing inheritance
:label: implementing-inheritance
Implement `BulkItem` and `UnitItem` which are based on the `Item` you implemented in {ref}`implementing-the-item-class`.

   - `BulkItem` can be a meter, kg, etc, item. Therefore it has a `string measurementUnit`.
   - `UnitItem` has a `decimal weight`.
:::

<!--

I removed this part, because redefining ToString requires `override`. otherwise an additional method with the same name is created I believe.

Imagine you want to augment a method provided by the base class. You can do this by defining the method again. To use existing functionality, you can use `base.MethodName()`.

:::{activity} Redefining methods of the base class
Based on {ref}`implementing-inheritance`, reimplement the method `ToString()` for `BulkItem`, so that the string you return additionally contains the measurement unit.

Use `base.ToString()` in `BulkItem.ToString()` to use the functionality that you have implemented before.
:::

-->
## Aggregation

An object can also *contain* one or many objects of another kind.

:::{mermaid}
classDiagram
class Plant {
    +string name
    +string species
    +string LookupPlantDatabase()
}
class Edible {
   +uint caloriesPer100g 
}
class Ornamental {
    +string color
}
class Garden {
    +List~Plant~ Plants
    +uint EdibleCount()
}
Garden o-- Plant
Plant <|-- Edible
Plant <|-- Ornamental
:::

`Garden` contains or aggregates many `Plant`s, this is depicted by the hollow diamond shape on the aggregating class. Class diagram above corresponds to the code below. 

Aggregation can be implemented with a collection datatype like `List`, `Map` etc.

:::{literalinclude} ../code/aggregation.cs
:language: cs
:::
Outputs:
```text
2
```

<!-- TODO I moved this activity to dictionary, think about another one-->

## Association

Association is the most general relationship, i.e., aggregation and inheritance are special relationships. We can use this for other relations:


Example:
```{mermaid}
classDiagram
class Plant {
    +string name
    +string species
    +string LookupPlantDatabase()
}
class Guest {
    +void Observe(Plant)
}
Guest --> Plant : observes
```

---

:::{activity} class diagram for Inventory system
:label: class-diagram-for-inventory-system
Convert your diagram from {ref}`visual-relation-between-concepts` to a class diagram. It is enough to show the relations, but add data fields and methods from last activities if you desire.

Hint: You can use <https://draw.io> do draw class diagrams. You find related shapes under `UML`, e.g., `Class`, `Aggregation 2` and `Generalization`.
:::

## Appendix

### Used resources
- [Key/value pair collections](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/collections#keyvalue-pair-collections)
- [How to initialize a dictionary with a collection initializer](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-initialize-a-dictionary-with-a-collection-initializer)
- [Primary constructors][primary-constructors]

[primary-constructors]: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/instance-constructors#primary-constructors

### Constructors

We can also create a method that is used for constructing instances. A constructor is a method that is used to create a new object from the class.

Using a method gives us also the possibility to include actions other than just merely setting a variable. For example the following code gives the plant a random name if no name is provided.

```cs
var p1 = new Plant("kale", "Kaiser");
Console.WriteLine(p1.Name);
var p2 = new Plant("Hortensia");
Console.WriteLine(p2.Name);

public class Plant
{
    public string Name;
    public string Species;

    public Plant(string species, string name = null)
    {
        Species = species;
        Name = name ?? Random.Shared.Next(1000, 10000).ToString();
    }

    public string LookupPlantsDatabase()
    {
        return "information";
    }
}
```
Output:
```text
Kaiser
7715
```

`Plant(...)` is called *constructor*. 

Additionally, code for instance creation becomes more concise by using constructors.

### Primary constructors

We can also shorten the code for class definition using a [*primary constructor*][primary-constructors]:

```cs
var p1 = new Plant("kale", "Kaiser");
Console.WriteLine(p1.Name);
var p2 = new Plant("Hortensia");
Console.WriteLine(p2.Name);

public class Plant(string species, string name = null)
{
    public string Name = name ?? Random.Shared.Next(1000, 10000).ToString();
    public string Species = species;

    public string LookupPlantsDatabase()
    {
        return "information";
    }
}
```

### Inheritance using primary constructor

In inheritance we use a constructor of the ancestor if we use a primary constructor. This means that first the ancestor method is called with given arguments and then the actions in the child's constructor.

:::{literalinclude} ../code/inheritance-using-primary-constructor.cs
:language: cs
:::

### Aggregation using primary constructor

Aggregation does not profit from primary constructor. This code is included here just for completeness.
:::{literalinclude} ../code/aggregation-using-primary-constructor.cs
:language: cs
:::