Programming C#

Tasks studies - laboratory


Project maintained by dawidolko Hosted on GitHub Pages — Theme by dawidolko

Object-oriented programming – C#

INHERITANCE, POLYMORPHISM, BASE, VIRTUAL METHODS, ABSTRACT, SEALED

Base and derived classes

A class can inherit from one class, but can implement multiple interfaces. Inheritance syntax: access_modifier class base_class

{
…
}
class klasa_pochodna : klasa_bazowa
{
…
}

Example

class Program
{
  static void Main(string[] args)
  {
    Prostokat pr = new Prostokat();
    pr.UstawSzerokosc(4);
    pr.UstawWysokosc(5);
    // Obliczenie powierzchni
    Console.WriteLine("Powierzchnia prostokąta: {0}", pr.ObliczPowirzchnie());
    Console.ReadKey();
    // Wynik działania programu
    // Powierzchnia prostokata: 20
  }
}
// klasa bazowa
class Ksztalt
{
  // modyfikator dostepu protected
  // pola dostepne sa dla klasy oraz klas, której po niej dziedziczą
  // gdybyśmy zastosowali modyfikator dostępu private
  // pole byłoby dostępne tylko dla tej klasy
  protected int szerokosc;
  protected int wysokosc;
  public void UstawWysokosc(int w)
  {
    wysokosc = w;
  }
  public void UstawSzerokosc(int s)
  {
    szerokosc = s;
  }
}
// klasa pochodna
class Prostokat : Ksztalt
{
    public int ObliczPowirzchnie()
  {
  // mamy dostęp do pól z klasy bazowej
    return wysokosc * szerokosc;
  }
}

Polymorphism

The concept of polymorphism in C# is related to inheritance. Polymorphism (Greek: Polýmorphos wieloformaciowy) means the ability to operate on objects belonging to different classes.

class Vehicle
{
public void TurnLeft()

{
Console.WriteLine("Hello it's TurnLeft() from Vehicle");
}
}
class Car : Vehicle
{
public void TurnLeft()

{
Console.WriteLine("Hello it's TurnLeft() from Car");
}
}

The Car class inherits from Vehicle. Both have a TurnLeft() method. If we create a new instance of the Car class and call the TurnLeft() method, the code from the Car class will be executed. However, the compiler will tell us that:

‘Car.TurnLeft()' hides inherited member ‘Vehicle.TurnLeft()'. Use the new keyword if hiding was
intended

Although this is not an error from the compiler’s perspective (it will compile), it is good practice to explicitly state that we know what we are doing and want to override an element previously declared in the base class. This is done with the new keyword. In this context, the keyword is used as an access modifier:

public new void TurnLeft()
{
Console.WriteLine("Hello it's TurnLeft() from Car");
}

The new modifier prevents the override message from appearing. This tells the compiler that we know that the base class has a TurnLeft() method, but that we want to declare a method with the same name in the derived class. This is not just true for class methods, but for all elements, including properties and fields. Similarly, we can override static elements

public class Vehicle
{
  public static int ACTUAL_MILEAGE = 100;
    public static void GetMileage()
    {
      Console.WriteLine($"Mileage {ACTUAL_MILEAGE}");
    }
  }
  public class Car : Vehicle
  {
    new public static readonly int ACTUAL_MILEAGE = 1000;
    public new static void GetMileage()
    {
      Console.WriteLine($"Mileage {ACTUAL_MILEAGE}");
  }
}

Wykorzystanie:

Vehicle.ACTUAL_MILEAGE = 1;
Car.ACTUAL_MILEAGE = 1; //ERROR

BASE

The base keyword is very important in the context of polymorphism because it allows us to access the elements of the base class:

public class Vehicle
{
  public int ACTUAL_MILEAGE = 100;
  public void GetMileage()
  {
    Console.WriteLine($"Mileage {ACTUAL_MILEAGE}");
  }
  }
  public class Car : Vehicle
  {
    new public readonly int ACTUAL_MILEAGE = 1000;
    public void GetInfo()
    {
      base.GetMileage();
    }
}

We have a more advanced use of the base keyword in constructors

public class Vehicle
{
  private string _manufacturer;
  public Vehicle() => _manufacturer = "BMW";
  public Vehicle(string manufacturer) => _manufacturer = manufacturer;
  public string Manufacturer
  {
  get
  {
  return _manufacturer;
  }
  set
    {
    _manufacturer = value;
    }
    }
  }
  public class Car : Vehicle
  {
  private string _model;
  public Car() => _model = "????";
  public Car(string model) : base("AUDI") => _model = model;
  public Car(string manufacturer, string model) : base(manufacturer) => _model = model;
  public string Model
  {
  set
    {
    _model = value;
    }
  }
  public string FullName
  {
  get
    {
    r  eturn $"{Manufacturer} {_model}";
    }
  }
}
var item1 = new Vehicle();
var item2 = new Vehicle("OPEL");
var item3 = new Car();
var item4 = new Car("A5");
var item5 = new Car("KIA", "POLICYJNA");
Console.WriteLine(item1.Manufacturer);
Console.WriteLine(item2.Manufacturer);
Console.WriteLine(item3.FullName);
Console.WriteLine(item4.FullName);
Console.WriteLine(item5.FullName);

OUTPUT:

BMW
OPEL
BMW ????
AUDI A5
KIA POLICYJNA

Virtual Methods

A virtual method is one that is prepared to be overridden in a derived class.

public class Vehicle
{
public virtual void TurnLeft() //metody virutal nie mogą być private
  {
    Console.WriteLine("GO GO GO");
  }
}

Overriding is the process of creating a new version of a method in a descendant class. It involves creating a method that has the override keyword:

public class Car : Vehicle
{
  public override void TurnLeft()
  {
    Console.WriteLine("Im Going left");
    base.TurnLeft();
  }
  }
  public class Train : Vehicle
  {
  public override void TurnLeft()
  {
    Console.WriteLine("How can I turn left??? ( ͡° ͜ʖ ͡°)");
  }
}

Program

static void Main(string[] args)
{
  Vehicle vehicle;
  Console.WriteLine("1-Car; 2-Train; def-Vehicle");
  var key = Console.ReadLine();
  switch (key)
  {
    case "1":
    vehicle = new Car();
    break;
    case "2":
    vehicle = new Train();
    break;
    default:
    vehicle = new Vehicle();
    break;
  }
    vehicle.TurnLeft();
    Console.ReadLine();
}

Output

Dla 1:
Im Going left
GO GO GO
Dla 2:
How can I turn left??? ( ͡° ͜ʖ ͡°)
Def:
GO GO GO

When we declare “Vehicle vehicle;” at the very beginning, we specify that all calls to the TurnLeft() method will refer to this class. This is the so-called early binding. If we use virtual methods, the compiler will refrain from deciding which class to assign a given method to. This decision will be made only during program execution. In our program above, it is made by the user using the 1, 2 or other keys. This solution is called late binding.

Abstract

In the previous examples, we had a base class Vehicle, containing the TurnLeft() method. But if we assume that we will not use the Vehicle class in the program, but descendant classes, there is no need to implement methods in this class. We can then use the abstract keyword. An abstract class has no implementation (i.e. method definitions), it only has headers (declarations):

abstract class Vehicle
{
public abstract void TurnLeft(); //Abstract methods cannot be private
}

Then the descendant classes must implement the abstract method:

public class Car : Vehicle
{
  public override void TurnLeft()
  {
    Console.WriteLine("Im Going left");
  }
  }
  public class Train : Vehicle //ERROR
  {
}

Sealed

Sealed – elements that are secured (sealed) cannot be used as base classes. We only use them when we have a serious reason to do so (e.g. security reasons). In such cases, remember not to use virtual methods or the protected modifier, because it makes no sense.

public sealed class Vehicle
{
}

Tasks to solve on your own:

1.

Implement the Shape class, which has the properties X, Y, Height, Width and the virtual Draw method. Then implement the classes:

• Rectangle,

• Triangle,

• Circle

Which will implement the draw method by printing to the console window what shape we are trying to draw. Then write a program that will add an object of each type from the inheriting classes to the List list. Then call the draw function for each element in the list.

2.

Write a program using polymorphism that will check whether a teacher can let students from his class go home without adult supervision:

Pesel Generator: link

  1. Create a project in which:

• Define a virtual class Person with fields:

o Name

o Surname

o Pesel

• • Define methods:

o SetFirstName

o SetLastName

o SetPesel

o GetAge

o GetGender //Position 10 (even women, odd men)

• Define methods

o GetEducationInfo

o GetFullName

o CanGoAloneToHome

  1. Add a Student class that inherits from the Person class;

• Contains additional properties:

o School

o CanGoHomeAlone

• Define methods:

o SetSchool o ChangeSchool

o SetCanGoHomeAlone

• Implements declared methods from Person class

o Info - Cannot go home alone under 12 years old unless they have permission

  1. Add Teacher class, which inherits from Student class:

• Contains additional properties:

o AcademicTitle

o Student collection - SubordinateStudents (students who are in teacher’s class)

• Define methods:

o WhichStudentCanGoHomeAlone(Datetime dateToCheck) [prints names of students who can go home alone]