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

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

Static, изключения и мини проект

Статични членове, обработка на грешки с try/catch и сглобяване — малка програма Library Manager, която обединява всичко научено.

Static — споделено между всички обекти

Обикновените полета и методи принадлежат на конкретен обект. Статичните принадлежат на самия клас — има само едно копие, независимо от броя обекти.

class Student
{
    public static int Count = 0;     // общо за всички Student

    public string Name;

    public Student(string name)
    {
        Name = name;
        Count++;                     // увеличаваме общия брой
    }
}

new Student("Иван");
new Student("Мария");
Console.WriteLine(Student.Count);   // 2 — не student.Count, а Student.Count!

Бележка

Статичните се извикват през името на класа (Student.Count, Math.Sqrt(...)), не през обект.

Статични методи

class MathHelper
{
    public static double Average(double[] arr)
    {
        double sum = 0;
        foreach (var x in arr) sum += x;
        return sum / arr.Length;
    }
}

double avg = MathHelper.Average(new[] { 3.0, 4.0, 5.0 });

Изобщо Math.Round, Console.WriteLine, int.Parse — всички са статични. Затова не пишеш new Math() първо.

Статичен клас

static class Logger
{
    public static void Log(string msg) => Console.WriteLine($"[LOG] {msg}");
}

// Logger.Log("Старт"); — без new

Статичен клас не може да има инстанции и съдържа само статични членове.

Изключения — try / catch / finally

Когато нещо се обърка (потребителят е въвел „abc" вместо число, файл не съществува, мрежата е изключена), нормалното изпълнение се прекратява и се хвърля изключение.

try
{
    Console.Write("Възраст: ");
    int age = int.Parse(Console.ReadLine());
    Console.WriteLine($"Възраст: {age}");
}
catch (FormatException)
{
    Console.WriteLine("Това не беше число.");
}
catch (Exception e)
{
    Console.WriteLine($"Неочаквана грешка: {e.Message}");
}
finally
{
    Console.WriteLine("Това винаги се изпълнява — и при успех, и при грешка.");
}
  • try — кода, който може да гръмне.
  • catch (КонкретенТип e) — какво да направим при този тип грешка.
  • finally — изпълнява се винаги (затваряне на файлове, връзки).
  • Хвани първо по-конкретните изключения, после общия Exception.

Хвърляне на собствено изключение

if (age < 0)
    throw new ArgumentException("Възрастта не може да е отрицателна.");

Мини проект — Library Manager

Сглобяваме всичко: класове, наследяване, интерфейс, капсулация, static, изключения, колекции.

using System;
using System.Collections.Generic;

interface IPrintable
{
    void Print();
}

abstract class LibraryItem : IPrintable
{
    public string Title { get; }
    public int Year { get; }

    protected LibraryItem(string title, int year)
    {
        if (string.IsNullOrWhiteSpace(title))
            throw new ArgumentException("Заглавието е задължително.");
        if (year < 1450) throw new ArgumentException("Невалидна година.");
        Title = title;
        Year = year;
    }

    public abstract string Kind { get; }
    public virtual void Print() => Console.WriteLine($"[{Kind}] {Title} ({Year})");
}

class Book : LibraryItem
{
    public string Author { get; }
    public Book(string title, string author, int year) : base(title, year)
    {
        Author = author;
    }
    public override string Kind => "Книга";
    public override void Print()
        => Console.WriteLine($"[{Kind}] {Title}, {Author} ({Year})");
}

class Magazine : LibraryItem
{
    public int Issue { get; }
    public Magazine(string title, int issue, int year) : base(title, year)
    {
        Issue = issue;
    }
    public override string Kind => "Списание";
    public override void Print()
        => Console.WriteLine($"[{Kind}] {Title}, бр. {Issue} ({Year})");
}

class Library
{
    private readonly List<LibraryItem> items = new();

    public int Count => items.Count;

    public void Add(LibraryItem item) => items.Add(item);

    public void PrintAll()
    {
        Console.WriteLine($"--- {Count} заглавия ---");
        foreach (var item in items) item.Print();
    }
}

class Program
{
    static void Main()
    {
        var lib = new Library();
        try
        {
            lib.Add(new Book("Под игото", "Иван Вазов", 1894));
            lib.Add(new Magazine("Тема", 12, 2025));
            lib.Add(new Book("Бай Ганьо", "Алеко Константинов", 1895));
        }
        catch (Exception e)
        {
            Console.WriteLine($"Не успях: {e.Message}");
        }

        lib.PrintAll();
    }
}

Какво научаваме от проекта

Програмата е малка, но използва всички ключови концепции на ООП: абстрактен клас (LibraryItem), наследяване (Book, Magazine), интерфейс (IPrintable), полиморфизъм (Print се държи различно), капсулация (private items + публични методи), валидация в конструктор, обработка на изключения.

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

  • Статичните членове принадлежат на класа, не на обекта (Math.PI, Student.Count).
  • try/catch/finally — за обработка на грешки.
  • throw new Exception(...) — за собствени проверки.
  • Мини проектите са най-добрият начин да усетиш ООП в действие.
  • ООП = моделиране на реалния свят с класове, които капсулират данни и поведение, наследяват и предоставят общи договори (интерфейси).