Лого на 91. НЕГ „Проф. Константин Гълъбов“

Модул 1 · Урок 12

Наследяване

Един клас взима всичко от друг — без дублиране. base, override, abstract класове.

Защо наследяване

Имаме клас Person с име и възраст. Сега искаме Student и Teacher — те също имат име и възраст, но всеки добавя свои неща (оценка / заплата).

Вместо да копираме същите полета в трите класа, наследяваме от общия родителски клас.

PersonName, AgeGreet()Student : Person+ Class, Grade+ Study()наследява Name, Age, Greet()Teacher : Person+ Subject, Salary+ Teach()наследява Name, Age, Greet()
Фиг. 1 — Student и Teacher наследяват общата структура от Person и добавят свои специфики

Синтаксис в C#

class Person
{
    public string Name;
    public int Age;

    public void Greet() => Console.WriteLine($"Здравей, аз съм {Name}.");
}

// Двоеточие = наследява от:
class Student : Person
{
    public double Grade;

    public void Study() => Console.WriteLine($"{Name} учи (оценка {Grade}).");
}

class Teacher : Person
{
    public string Subject;
    public void Teach() => Console.WriteLine($"{Name} преподава {Subject}.");
}

class Program
{
    static void Main()
    {
        var s = new Student { Name = "Иван", Age = 17, Grade = 5.50 };
        s.Greet();   // от Person
        s.Study();   // от Student
    }
}

Ключово

Student разполага с всичко от Person + своите си добавки. Това се нарича is-a връзка: „студентът Е човек".

Конструктори и base

Когато създаваш Student, първо трябва да се извика конструкторът на Person. За това има ключова дума base:

class Person
{
    public string Name;
    public int Age;
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

class Student : Person
{
    public double Grade;
    public Student(string name, int age, double grade)
        : base(name, age)        // ← извиква конструктора на Person
    {
        Grade = grade;
    }
}

var s = new Student("Иван", 17, 5.50);

virtual и override — преписване на метод

Понякога наследникът иска друго поведение за същия метод:

class Person
{
    public string Name;
    public virtual void Greet()   // virtual = може да се препише
        => Console.WriteLine($"Здравей, аз съм {Name}.");
}

class Teacher : Person
{
    public string Subject;
    public override void Greet()  // override = заменям
        => Console.WriteLine($"Здравейте, аз съм г-н {Name}, преподавам {Subject}.");
}

var t = new Teacher { Name = "Петров", Subject = "Информатика" };
t.Greet();   // "Здравейте, аз съм г-н Петров..."

Извикване на родителския метод с base

public override void Greet()
{
    base.Greet();   // първо родителския
    Console.WriteLine("…и съм учител!");
}

Абстрактни класове

Понякога базовият клас няма смисъл сам по себе си — само като „шаблон" за подкласове. Маркира се с abstract:

abstract class Shape
{
    public abstract double Area();          // няма тяло — наследникът трябва да го имплементира

    public void Describe()                   // обикновен метод — наследен от всички
        => Console.WriteLine($"Площ: {Area():F2}");
}

class Circle : Shape
{
    public double Radius;
    public override double Area() => Math.PI * Radius * Radius;
}

class Rectangle : Shape
{
    public double Width, Height;
    public override double Area() => Width * Height;
}

// var s = new Shape();   // ❌ не може — абстрактен клас не се инстанцира
var c = new Circle { Radius = 5 };
c.Describe();   // Площ: 78.54

sealed — забранява по-нататъшно наследяване

sealed class FinalClass : SomeBase
{
    // никой не може да наследи FinalClass
}

Какво трябва да запомниш

  • class B : A — B наследява всичко от A.
  • base(...) в конструктора — извиква конструктора на родителя.
  • virtual в родителя + override в наследника — нов вариант на метод.
  • Абстрактен клас не се инстанцира; наследниците трябва да реализират abstract методите.
  • Наследяване ползвай за „is-a" връзки, не само за многократно ползване.