Class diagram#

We have already introduced basic concepts of OOP in section Fundamental concepts in object-oriented programming.

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:

class diagram
        classDiagram
class Plant {
    +string Name
    +string Species
    +string LookupPlantDatabase()
}
    
class implementations
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 35 (Implementing the item class)

Implement the class Item, which has the following data and methods:

  • name

  • price per unit

  • string ToString() that returns:

    {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.

inheritance

mechanism of basing a class or object upon another class, retaining similar implementation

class diagram
        classDiagram
class Plant {
    +string name
    +string species
    +string LookupPlantDatabase()
}
class Edible {
   +uint caloriesPer100g 
}
class Ornamental {
    +string color
}
Plant <|-- Edible
Plant <|-- Ornamental
    
class implementations
var e = new Edible
{
    Name = "Bas",
    Species = "Basil",
    CaloriesPer100g = 23
};
var o = new Ornamental
{
    Name = "Rosalinda",
    Species = "Rosa",
    Color = "yellow"
};
Console.WriteLine(o.LookupPlantsDatabase());

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

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

public class Edible : Plant
{
    public uint CaloriesPer100g;
}

public class Ornamental : Plant
{
    public string Color;
}

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 36 (Implementing inheritance)

Implement BulkItem and UnitItem which are based on the Item you implemented in Activity 35.

  • BulkItem can be a meter, kg, etc, item. Therefore it has a string measurementUnit.

  • UnitItem has a decimal weight.

Aggregation#

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

        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 Plants, 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.

var e0 = new Edible { Name = "Bas", Species = "Basil", CaloriesPer100G = 23 };
var e1 = new Edible { Name = "Karsten", Species = "kale", CaloriesPer100G = 50 };
var o0 = new Ornamental { Name = "Rosalinda", Species = "Rosa", Color = "yellow" };
var g = new Garden { Name = "Front", Plants = [e0, e1, o0] };
Console.WriteLine(g.EdibleCount());

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

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

public class Edible : Plant
{
    public uint CaloriesPer100G;
}

public class Ornamental : Plant
{
    public string Color;
}

public class Garden
{
    public string Name;
    public List<Plant> Plants;

    public uint EdibleCount()
    {
        uint count = 0;
        foreach (var plant in Plants)
            if (plant is Edible)
                ++count;
        return count;
    }
}

Outputs:

2

Association#

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

Example:

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

Activity 37 (class diagram for Inventory system)

Convert your diagram from Activity 34 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#

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.

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:

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:

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.

var e = new Edible("Bas", "Basil", 23);
var o = new Ornamental("Rosalinda", "Rosa", "yellow")
Console.WriteLine(o.LookupPlantsDatabase());

public class Plant(string name, string species)
{
    public string Name = name;
    public string Species = species;

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

public class Edible(string name, string species, uint caloriesPer100G) : Plant(name, species)
{
    public uint CaloriesPer100G = caloriesPer100G;
}

public class Ornamental(string name, string species, string color) : Plant(name, species)
{
    public string Color = color;
}

Aggregation using primary constructor#

Aggregation does not profit from primary constructor. This code is included here just for completeness.

var e0 = new Edible("Bas", "Basil", 23);
var e1 = new Edible("Karsten", "kale", 50);
var o0 = new Ornamental("Rosalinda", "Rosa", "yellow");
var g = new Garden("Front", [e0, e1, o0]);
Console.WriteLine(g.EdibleCount());

public class Plant(string name, string species)
{
    public string Name = name;
    public string Species = species;

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

public class Edible(string name, string species, uint caloriesPer100g) : Plant(name, species)
{
    public uint CaloriesPer100g = caloriesPer100g;
}

public class Ornamental(string name, string species, string color) : Plant(name, species)
{
    public string Color = color;
}

public class Garden(string name, List<Plant> plants)
{
    public string Name = name;
    public List<Plant> Plants = plants;

    public uint EdibleCount()
    {
        uint count = 0;
        foreach (var plant in Plants)
            if (plant is Edible)
                ++count;
        return count;
    }
}