Защо наследяване
Имаме клас Person с име и възраст. Сега искаме Student и Teacher — те също имат име и възраст, но всеки добавя свои неща (оценка / заплата).
Вместо да копираме същите полета в трите класа, наследяваме от общия родителски клас.
Синтаксис в 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.54sealed — забранява по-нататъшно наследяване
sealed class FinalClass : SomeBase
{
// никой не може да наследи FinalClass
}Какво трябва да запомниш
class B : A— B наследява всичко от A.base(...)в конструктора — извиква конструктора на родителя.virtualв родителя +overrideв наследника — нов вариант на метод.- Абстрактен клас не се инстанцира; наследниците трябва да реализират
abstractметодите. - Наследяване ползвай за „is-a" връзки, не само за многократно ползване.