Tasks studies - laboratory
A class can inherit from one class, but can implement multiple interfaces. Inheritance syntax: access_modifier class base_class
{
…
}
class klasa_pochodna : klasa_bazowa
{
…
}
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;
}
}
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
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
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??? ( ͡° ͜ʖ ͡°)");
}
}
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.
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 – 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
{
}
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
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
• 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
• 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
• 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]