۵

برنامه‌نویسی شیءگرا (OOP) 🏗️🎯

وقتشه کدهامون رو مثل دنیای واقعی سازماندهی کنیم!

🎯 برنامه‌نویسی شیءگرا چیست؟

برنامه‌نویسی شیءگرا (Object-Oriented Programming) یک روش برنامه‌نویسی است که به ما کمک می‌کند کدهایمان را مثل دنیای واقعی سازماندهی کنیم. تصور کنید می‌خواهید یک بازی کامپیوتری بسازید - در این بازی شخصیت‌ها، اشیاء، و محیط‌های مختلفی وجود دارد. هر کدام از این‌ها ویژگی‌ها و رفتارهای خاص خودشان را دارند.

🔑 چهار اصل اساسی OOP:

  • کپسوله‌سازی (Encapsulation): مخفی کردن جزئیات داخلی
  • وراثت (Inheritance): به ارث بردن ویژگی‌ها از کلاس والد
  • چندریختی (Polymorphism): یک رابط، رفتارهای مختلف
  • انتزاع (Abstraction): ساده‌سازی پیچیدگی‌ها

🏗️ کلاس و شیء چیست؟

کلاس (Class) مثل یک نقشه یا قالب است که مشخص می‌کند یک شیء چه ویژگی‌ها و رفتارهایی دارد. شیء (Object) نمونه‌ای از آن کلاس است که در حافظه ساخته می‌شود.

🌟 مثال از زندگی واقعی:

کلاس "خودرو" مثل نقشه‌ای است که مشخص می‌کند هر خودرویی باید برند، مدل، رنگ داشته باشد و بتواند روشن/خاموش شود. "پراید آبی من" یک شیء از این کلاس است!

📝 ساختار کلی یک کلاس:

ساختار کلی کلاس در C#
public class ClassName
{
    // فیلدها (Fields) - متغیرهای داخلی کلاس
    private int _privateField;
    
    // ویژگی‌ها (Properties) - دسترسی کنترل شده به داده‌ها
    public string PropertyName { get; set; }
    
    // سازنده (Constructor) - برای مقداردهی اولیه
    public ClassName(parameters)
    {
        // مقداردهی اولیه
    }
    
    // متدها (Methods) - رفتارهای کلاس
    public void MethodName()
    {
        // کدهای متد
    }
}

🚗 مثال عملی: کلاس خودرو

تعریف کلاس خودرو و ساخت شیء
using System;

// تعریف کلاس خودرو
public class Car
{
    // فیلدهای خصوصی (Private Fields)
    private string _engineType;
    private bool _isRunning;
    
    // ویژگی‌های عمومی (Public Properties)
    public string Brand { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
    public string Color { get; set; }
    public int Mileage { get; private set; } // فقط خواندنی از بیرون
    
    // سازنده (Constructor)
    public Car(string brand, string model, int year, string color, string engineType)
    {
        Brand = brand;
        Model = model;
        Year = year;
        Color = color;
        _engineType = engineType;
        _isRunning = false;
        Mileage = 0;
        
        Console.WriteLine($"خودروی {Brand} {Model} ساخته شد! 🚗");
    }
    
    // متدهای عمومی (Public Methods)
    public void Start()
    {
        if (!_isRunning)
        {
            _isRunning = true;
            Console.WriteLine($"{Brand} {Model} با موتور {_engineType} روشن شد! 🔥");
        }
        else
        {
            Console.WriteLine("خودرو از قبل روشن است!");
        }
    }
    
    public void Stop()
    {
        if (_isRunning)
        {
            _isRunning = false;
            Console.WriteLine($"{Brand} {Model} خاموش شد! 🛑");
        }
        else
        {
            Console.WriteLine("خودرو از قبل خاموش است!");
        }
    }
    
    public void Drive(int distance)
    {
        if (_isRunning)
        {
            Mileage += distance;
            Console.WriteLine($"{distance} کیلومتر رانندگی کردید. کل کیلومتر: {Mileage}");
        }
        else
        {
            Console.WriteLine("ابتدا خودرو را روشن کنید!");
        }
    }
    
    // متد برای نمایش اطلاعات
    public void DisplayInfo()
    {
        Console.WriteLine($"\n--- اطلاعات خودرو ---");
        Console.WriteLine($"برند: {Brand}");
        Console.WriteLine($"مدل: {Model}");
        Console.WriteLine($"سال: {Year}");
        Console.WriteLine($"رنگ: {Color}");
        Console.WriteLine($"کیلومتر: {Mileage}");
        Console.WriteLine($"وضعیت: {(_isRunning ? "روشن" : "خاموش")}");
        Console.WriteLine($"نوع موتور: {_engineType}");
    }
}

class Program
{
    static void Main()
    {
        // ساخت اشیاء مختلف از کلاس خودرو
        Car car1 = new Car("تویوتا", "کمری", 2023, "سفید", "هیبریدی");
        Car car2 = new Car("بنز", "C200", 2024, "مشکی", "توربو");
        
        Console.WriteLine("\n=== تست خودروی اول ===");
        car1.DisplayInfo();
        car1.Start();
        car1.Drive(50);
        car1.Drive(30);
        car1.Stop();
        
        Console.WriteLine("\n=== تست خودروی دوم ===");
        car2.DisplayInfo();
        car2.Drive(20); // خطا: خودرو روشن نیست
        car2.Start();
        car2.Drive(20);
        
        Console.WriteLine("\n=== اطلاعات نهایی ===");
        car1.DisplayInfo();
        car2.DisplayInfo();
        
        Console.ReadKey();
    }
}

🔍 تحلیل کد:

  • فیلدهای خصوصی: `_engineType` و `_isRunning` از بیرون قابل دسترسی نیستند
  • Properties: `Brand`, `Model` قابل خواندن و نوشتن، `Mileage` فقط خواندنی
  • Constructor: مقادیر اولیه را تنظیم می‌کند
  • Methods: رفتارهای مختلف خودرو را پیاده‌سازی می‌کنند
  • Encapsulation: داده‌های حساس محافظت شده‌اند

🔒 کپسوله‌سازی (Encapsulation)

کپسوله‌سازی یعنی مخفی کردن جزئیات داخلی کلاس و فقط اجازه دسترسی کنترل شده به آن‌ها. مثل یک خانه که درب و پنجره دارد اما اتاق‌های خصوصی آن قابل دسترسی نیست.

🔑 سطوح دسترسی در C#:

  • public: از همه جا قابل دسترسی
  • private: فقط داخل همان کلاس
  • protected: داخل کلاس و کلاس‌های فرزند
  • internal: داخل همان Assembly
مثال کپسوله‌سازی: کلاس حساب بانکی
using System;

public class BankAccount
{
    // فیلدهای خصوصی - از بیرون قابل دسترسی نیستند
    private decimal _balance;
    private string _accountNumber;
    private string _pin;
    
    // ویژگی‌های عمومی با کنترل دسترسی
    public string AccountHolder { get; private set; }
    public decimal Balance 
    { 
        get { return _balance; } // فقط خواندنی از بیرون
    }
    
    // سازنده
    public BankAccount(string accountHolder, string accountNumber, string pin)
    {
        AccountHolder = accountHolder;
        _accountNumber = accountNumber;
        _pin = pin;
        _balance = 0;
        Console.WriteLine($"حساب بانکی برای {AccountHolder} ایجاد شد.");
    }
    
    // متد عمومی برای واریز
    public void Deposit(decimal amount)
    {
        if (amount > 0)
        {
            _balance += amount;
            Console.WriteLine($"{amount:C} واریز شد. موجودی: {_balance:C}");
        }
        else
        {
            Console.WriteLine("مبلغ واریز باید مثبت باشد!");
        }
    }
    
    // متد عمومی برای برداشت با احراز هویت
    public bool Withdraw(decimal amount, string pin)
    {
        if (!ValidatePin(pin))
        {
            Console.WriteLine("رمز عبور اشتباه است!");
            return false;
        }
        
        if (amount <= 0)
        {
            Console.WriteLine("مبلغ برداشت باید مثبت باشد!");
            return false;
        }
        
        if (amount > _balance)
        {
            Console.WriteLine("موجودی کافی نیست!");
            return false;
        }
        
        _balance -= amount;
        Console.WriteLine($"{amount:C} برداشت شد. موجودی: {_balance:C}");
        return true;
    }
    
    // متد خصوصی برای احراز هویت
    private bool ValidatePin(string pin)
    {
        return _pin == pin;
    }
    
    // متد عمومی برای نمایش اطلاعات (بدون اطلاعات حساس)
    public void DisplayAccountInfo()
    {
        Console.WriteLine($"\n--- اطلاعات حساب ---");
        Console.WriteLine($"صاحب حساب: {AccountHolder}");
        Console.WriteLine($"شماره حساب: {_accountNumber.Substring(0, 4)}****");
        Console.WriteLine($"موجودی: {_balance:C}");
    }
}

class Program
{
    static void Main()
    {
        BankAccount account = new BankAccount("احمد محمدی", "1234567890", "1234");
        
        // تست عملیات
        account.Deposit(1000000);
        account.Withdraw(200000, "1234"); // رمز درست
        account.Withdraw(100000, "5678"); // رمز غلط
        account.DisplayAccountInfo();
        
        // تلاش برای دسترسی مستقیم به فیلدهای خصوصی (خطا می‌دهد)
        // account._balance = 999999; // کامپایل نمی‌شود!
        // account._pin = "0000"; // کامپایل نمی‌شود!
        
        Console.ReadKey();
    }
}

🧬 وراثت (Inheritance)

وراثت به ما اجازه می‌دهد کلاس جدیدی بسازیم که ویژگی‌ها و رفتارهای کلاس دیگری را به ارث ببرد. مثل اینکه فرزندان ویژگی‌هایی از والدین خود به ارث می‌برند.

🌳 مزایای وراثت:

  • کاهش تکرار کد: کدهای مشترک در کلاس والد نوشته می‌شود
  • سازماندهی بهتر: ساختار سلسله مراتبی منطقی
  • قابلیت توسعه: اضافه کردن ویژگی‌های جدید به راحتی
  • چندریختی: امکان استفاده یکسان از اشیاء مختلف
مثال وراثت: سیستم وسایل نقلیه
using System;

// کلاس پایه (Base Class)
public class Vehicle
{
    // فیلدهای محافظت شده - قابل دسترسی در کلاس‌های فرزند
    protected string _engine;
    protected bool _isRunning;
    
    // ویژگی‌های عمومی
    public string Brand { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
    public int MaxSpeed { get; protected set; }
    
    // سازنده کلاس پایه
    public Vehicle(string brand, string model, int year, string engine, int maxSpeed)
    {
        Brand = brand;
        Model = model;
        Year = year;
        _engine = engine;
        MaxSpeed = maxSpeed;
        _isRunning = false;
        Console.WriteLine($"وسیله نقلیه {Brand} {Model} ساخته شد.");
    }
    
    // متد مجازی - قابل بازنویسی در کلاس‌های فرزند
    public virtual void Start()
    {
        if (!_isRunning)
        {
            _isRunning = true;
            Console.WriteLine($"{Brand} {Model} با موتور {_engine} روشن شد!");
        }
    }
    
    public virtual void Stop()
    {
        if (_isRunning)
        {
            _isRunning = false;
            Console.WriteLine($"{Brand} {Model} خاموش شد!");
        }
    }
    
    // متد عمومی مشترک
    public void DisplayBasicInfo()
    {
        Console.WriteLine($"برند: {Brand}, مدل: {Model}, سال: {Year}");
        Console.WriteLine($"حداکثر سرعت: {MaxSpeed} کیلومتر، وضعیت: {(_isRunning ? "روشن" : "خاموش")}");
    }
}

// کلاس فرزند: خودروی مسابقه‌ای
public class SportsCar : Vehicle
{
    public bool TurboMode { get; private set; }
    public int TurboBoost { get; private set; }
    
    // سازنده که سازنده والد را فراخوانی می‌کند
    public SportsCar(string brand, string model, int year, string engine, int maxSpeed, int turboBoost) 
        : base(brand, model, year, engine, maxSpeed)
    {
        TurboBoost = turboBoost;
        TurboMode = false;
        Console.WriteLine($"ماشین مسابقه‌ای با قابلیت توربو {turboBoost} اسب بخار اضافه شد!");
    }
    
    // بازنویسی متد والد (Override)
    public override void Start()
    {
        if (!_isRunning)
        {
            _isRunning = true;
            Console.WriteLine($"🏎️ ماشین مسابقه‌ای {Brand} {Model} با صدای خفن روشن شد!");
            Console.WriteLine($"آماده برای سرعت تا {MaxSpeed} کیلومتر!");
        }
    }
    
    // متد اختصاصی کلاس فرزند
    public void ActivateTurbo()
    {
        if (_isRunning && !TurboMode)
        {
            TurboMode = true;
            Console.WriteLine($"🚀 توربو فعال شد! قدرت اضافی: {TurboBoost} اسب بخار!");
            Console.WriteLine($"حداکثر سرعت جدید: {MaxSpeed + 50} کیلومتر!");
        }
        else if (!_isRunning)
        {
            Console.WriteLine("ابتدا خودرو را روشن کنید!");
        }
        else
        {
            Console.WriteLine("توربو از قبل فعال است!");
        }
    }
    
    public void DeactivateTurbo()
    {
        if (TurboMode)
        {
            TurboMode = false;
            Console.WriteLine("توربو غیرفعال شد.");
        }
    }
}

// کلاس فرزند: کامیون
public class Truck : Vehicle
{
    public int LoadCapacity { get; private set; }
    public int CurrentLoad { get; private set; }
    
    public Truck(string brand, string model, int year, string engine, int maxSpeed, int loadCapacity) 
        : base(brand, model, year, engine, maxSpeed)
    {
        LoadCapacity = loadCapacity;
        CurrentLoad = 0;
        Console.WriteLine($"کامیون با ظرفیت {loadCapacity} تن ساخته شد.");
    }
    
    public override void Start()
    {
        if (!_isRunning)
        {
            _isRunning = true;
            Console.WriteLine($"🚛 کامیون {Brand} {Model} با موتور قدرتمند {_engine} روشن شد!");
            Console.WriteLine($"بار فعلی: {CurrentLoad}/{LoadCapacity} تن");
        }
    }
    
    public void LoadCargo(int weight)
    {
        if (CurrentLoad + weight <= LoadCapacity)
        {
            CurrentLoad += weight;
            Console.WriteLine($"{weight} تن بار اضافه شد. بار کل: {CurrentLoad}/{LoadCapacity} تن");
        }
        else
        {
            Console.WriteLine($"ظرفیت کافی نیست! حداکثر {LoadCapacity - CurrentLoad} تن می‌توانید اضافه کنید.");
        }
    }
    
    public void UnloadCargo(int weight)
    {
        if (weight <= CurrentLoad)
        {
            CurrentLoad -= weight;
            Console.WriteLine($"{weight} تن بار تخلیه شد. بار باقی‌مانده: {CurrentLoad} تن");
        }
        else
        {
            Console.WriteLine($"فقط {CurrentLoad} تن بار موجود است!");
        }
    }
}

class Program
{
    static void Main()
    {
        Console.WriteLine("=== تست ماشین مسابقه‌ای ===");
        SportsCar ferrari = new SportsCar("فراری", "F8 Tributo", 2024, "V8 Twin-Turbo", 340, 200);
        ferrari.DisplayBasicInfo();
        ferrari.Start();
        ferrari.ActivateTurbo();
        ferrari.Stop();
        
        Console.WriteLine("\n=== تست کامیون ===");
        Truck truck = new Truck("ولوو", "FH16", 2023, "دیزل", 120, 25);
        truck.DisplayBasicInfo();
        truck.Start();
        truck.LoadCargo(15);
        truck.LoadCargo(12); // بیش از ظرفیت
        truck.UnloadCargo(5);
        truck.Stop();
        
        Console.WriteLine("\n=== تست چندریختی ===");
        Vehicle[] vehicles = { ferrari, truck };
        foreach (Vehicle vehicle in vehicles)
        {
            Console.WriteLine($"\nشروع {vehicle.Brand} {vehicle.Model}:");
            vehicle.Start(); // هر کدام متد خودشان را اجرا می‌کنند
        }
        
        Console.ReadKey();
    }
}

🎭 چندریختی (Polymorphism)

چندریختی یعنی توانایی استفاده از یک رابط واحد برای انواع مختلف اشیاء. مثل اینکه همه حیوانات صدا می‌دهند، اما هر کدام صدای متفاوتی دارند.

مثال چندریختی: سیستم حیوانات
using System;
using System.Collections.Generic;

// کلاس پایه انتزاعی
public abstract class Animal
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    public Animal(string name, int age)
    {
        Name = name;
        Age = age;
    }
    
    // متد انتزاعی - باید در کلاس‌های فرزند پیاده‌سازی شود
    public abstract void MakeSound();
    public abstract void Move();
    
    // متد مجازی - می‌تواند بازنویسی شود
    public virtual void Eat()
    {
        Console.WriteLine($"{Name} در حال خوردن است.");
    }
    
    // متد عمومی
    public void Sleep()
    {
        Console.WriteLine($"{Name} در حال خوابیدن است. 😴");
    }
}

public class Dog : Animal
{
    public string Breed { get; set; }
    
    public Dog(string name, int age, string breed) : base(name, age)
    {
        Breed = breed;
    }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{Name} (سگ {Breed}) می‌گوید: واق واق! 🐕");
    }
    
    public override void Move()
    {
        Console.WriteLine($"{Name} در حال دویدن و بازی است!");
    }
    
    public override void Eat()
    {
        Console.WriteLine($"{Name} غذای سگ می‌خورد. 🦴");
    }
    
    // متد اختصاصی
    public void Fetch()
    {
        Console.WriteLine($"{Name} توپ را می‌آورد!");
    }
}

public class Cat : Animal
{
    public bool IsIndoor { get; set; }
    
    public Cat(string name, int age, bool isIndoor) : base(name, age)
    {
        IsIndoor = isIndoor;
    }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{Name} (گربه {(IsIndoor ? "خانگی" : "ولگرد")}) می‌گوید: میو میو! 🐱");
    }
    
    public override void Move()
    {
        Console.WriteLine($"{Name} با ظرافت راه می‌رود.");
    }
    
    public override void Eat()
    {
        Console.WriteLine($"{Name} غذای گربه می‌خورد. 🐟");
    }
    
    public void Purr()
    {
        Console.WriteLine($"{Name} خرخر می‌کند! 😸");
    }
}

public class Bird : Animal
{
    public bool CanFly { get; set; }
    
    public Bird(string name, int age, bool canFly) : base(name, age)
    {
        CanFly = canFly;
    }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{Name} (پرنده) می‌گوید: جیک جیک! 🐦");
    }
    
    public override void Move()
    {
        if (CanFly)
            Console.WriteLine($"{Name} در آسمان پرواز می‌کند! ✈️");
        else
            Console.WriteLine($"{Name} روی زمین راه می‌رود.");
    }
    
    public override void Eat()
    {
        Console.WriteLine($"{Name} دانه می‌خورد. 🌾");
    }
}

class Program
{
    static void Main()
    {
        // ایجاد لیستی از حیوانات مختلف
        List animals = new List
        {
            new Dog("رکس", 3, "ژرمن شپرد"),
            new Cat("مینو", 2, true),
            new Bird("طوطی", 1, true),
            new Dog("بادی", 5, "گلدن رتریور"),
            new Cat("گربه سیاه", 4, false)
        };
        
        Console.WriteLine("=== نمایش چندریختی ===");
        
        // استفاده از چندریختی - همه حیوانات با یک روش کنترل می‌شوند
        foreach (Animal animal in animals)
        {
            Console.WriteLine($"\n--- {animal.Name} ({animal.Age} ساله) ---");
            animal.MakeSound();  // هر حیوان صدای خودش را در می‌آورد
            animal.Move();       // هر حیوان به شیوه خودش حرکت می‌کند
            animal.Eat();        // هر حیوان غذای خودش را می‌خورد
            animal.Sleep();      // همه یکسان می‌خوابند
        }
        
        Console.WriteLine("\n=== تست متدهای اختصاصی ===");
        
        // دسترسی به متدهای اختصاصی با Type Casting
        foreach (Animal animal in animals)
        {
            if (animal is Dog dog)
            {
                dog.Fetch();
            }
            else if (animal is Cat cat)
            {
                cat.Purr();
            }
        }
        
        Console.WriteLine("\n=== شمارش انواع حیوانات ===");
        CountAnimals(animals);
        
        Console.ReadKey();
    }
    
    // متد برای شمارش انواع حیوانات
    static void CountAnimals(List animals)
    {
        int dogCount = 0, catCount = 0, birdCount = 0;
        
        foreach (Animal animal in animals)
        {
            switch (animal)
            {
                case Dog _:
                    dogCount++;
                    break;
                case Cat _:
                    catCount++;
                    break;
                case Bird _:
                    birdCount++;
                    break;
            }
        }
        
        Console.WriteLine($"سگ‌ها: {dogCount}, گربه‌ها: {catCount}, پرندگان: {birdCount}");
    }
}

🚗 مثال اضافی: سیستم وسایل نقلیه

در این مثال، یک سیستم ساده برای وسایل نقلیه ایجاد می‌کنیم که شامل کلاس پایه Vehicle و کلاس فرزند SportsCar است.

// کلاس پایه وسیله نقلیه
public class Vehicle
{
    private string _engine;
    public string Brand { get; set; }
    
    // ویژگی عمومی (Public Property)
    public int Year { get; set; }
    
    // سازنده
    public Vehicle(string brand, int year, string engine)
    {
        Brand = brand;
        Year = year;
        _engine = engine;
    }
    
    // متد مجازی (Virtual Method)
    public virtual void Start()
    {
        Console.WriteLine($"{Brand} با موتور {_engine} روشن شد!");
    }
}

// کلاس فرزند (Derived Class)
public class SportsCar : Vehicle
{
    public int TopSpeed { get; set; }
    
    // سازنده که سازنده والد را فراخوانی می‌کند
    public SportsCar(string brand, int year, string engine, int topSpeed) 
        : base(brand, year, engine)
    {
        TopSpeed = topSpeed;
    }
    
    // بازنویسی متد والد (Override)
    public override void Start()
    {
        Console.WriteLine($"ماشین مسابقه‌ای {Brand} با صدای خفن روشن شد! 🏎️");
    }
    
    // متد اختصاصی
    public void Turbo()
    {
        Console.WriteLine($"توربو فعال! سرعت تا {TopSpeed} کیلومتر!");
    }
}

class Program
{
    static void Main()
    {
        SportsCar ferrari = new SportsCar("فراری", 2024, "V8", 350);
        ferrari.Start();
        ferrari.Turbo();
    }
}

💪 تمرین‌های عملی

حالا وقت تمرین است! این تمرین‌ها به شما کمک می‌کنند مفاهیم OOP را عمیق‌تر درک کنید.

🎓 تمرین ۱: سیستم مدیریت کتابخانه

یک سیستم کتابخانه طراحی کنید که شامل موارد زیر باشد:

  • کلاس پایه LibraryItem با ویژگی‌های عنوان، شناسه، سال انتشار و وضعیت امانت
  • کلاس Book که از LibraryItem ارث‌بری کند و نویسنده و تعداد صفحات داشته باشد
  • کلاس Magazine که از LibraryItem ارث‌بری کند و شماره مجله داشته باشد
  • متدهای امانت دادن و برگرداندن آیتم‌ها
  • متد جستجو بر اساس عنوان

جواب تمرین ۱: سیستم مدیریت کتابخانه

using System;
using System.Collections.Generic;
using System.Linq;

// کلاس پایه آیتم کتابخانه
public abstract class LibraryItem
{
    protected string _id;
    protected bool _isBorrowed;
    
    public string Title { get; set; }
    public string Id { get { return _id; } }
    public int PublishYear { get; set; }
    public bool IsBorrowed { get { return _isBorrowed; } }
    public DateTime? BorrowDate { get; private set; }
    public string BorrowerName { get; private set; }
    
    public LibraryItem(string id, string title, int publishYear)
    {
        _id = id;
        Title = title;
        PublishYear = publishYear;
        _isBorrowed = false;
    }
    
    // متد مجازی برای نمایش اطلاعات
    public virtual void DisplayInfo()
    {
        Console.WriteLine($"شناسه: {_id}, عنوان: {Title}, سال انتشار: {PublishYear}");
        Console.WriteLine($"وضعیت: {(_isBorrowed ? $"امانت داده شده به {BorrowerName}" : "موجود")}");
    }
    
    // متد امانت دادن
    public virtual bool Borrow(string borrowerName)
    {
        if (!_isBorrowed)
        {
            _isBorrowed = true;
            BorrowerName = borrowerName;
            BorrowDate = DateTime.Now;
            Console.WriteLine($"{Title} به {borrowerName} امانت داده شد.");
            return true;
        }
        else
        {
            Console.WriteLine($"{Title} در حال حاضر امانت داده شده است.");
            return false;
        }
    }
    
    // متد برگرداندن
    public virtual bool Return()
    {
        if (_isBorrowed)
        {
            Console.WriteLine($"{Title} از {BorrowerName} برگردانده شد.");
            _isBorrowed = false;
            BorrowerName = null;
            BorrowDate = null;
            return true;
        }
        else
        {
            Console.WriteLine($"{Title} امانت داده نشده است.");
            return false;
        }
    }
    
    // متد انتزاعی برای محاسبه جریمه
    public abstract decimal CalculateFine();
}

// کلاس کتاب
public class Book : LibraryItem
{
    public string Author { get; set; }
    public int PageCount { get; set; }
    public string Genre { get; set; }
    
    public Book(string id, string title, int publishYear, string author, int pageCount, string genre) 
        : base(id, title, publishYear)
    {
        Author = author;
        PageCount = pageCount;
        Genre = genre;
    }
    
    public override void DisplayInfo()
    {
        Console.WriteLine($"📚 کتاب: {Title}");
        Console.WriteLine($"نویسنده: {Author}, ژانر: {Genre}");
        Console.WriteLine($"تعداد صفحات: {PageCount}, سال انتشار: {PublishYear}");
        Console.WriteLine($"وضعیت: {(_isBorrowed ? $"امانت داده شده به {BorrowerName}" : "موجود")}");
    }
    
    public override decimal CalculateFine()
    {
        if (_isBorrowed && BorrowDate.HasValue)
        {
            int daysLate = (DateTime.Now - BorrowDate.Value).Days - 14; // مهلت ۱۴ روزه
            return daysLate > 0 ? daysLate * 1000 : 0; // ۱۰۰۰ تومان در روز
        }
        return 0;
    }
}

// کلاس مجله
public class Magazine : LibraryItem
{
    public int IssueNumber { get; set; }
    public string Publisher { get; set; }
    
    public Magazine(string id, string title, int publishYear, int issueNumber, string publisher) 
        : base(id, title, publishYear)
    {
        IssueNumber = issueNumber;
        Publisher = publisher;
    }
    
    public override void DisplayInfo()
    {
        Console.WriteLine($"📰 مجله: {Title}");
        Console.WriteLine($"ناشر: {Publisher}, شماره: {IssueNumber}");
        Console.WriteLine($"سال انتشار: {PublishYear}");
        Console.WriteLine($"وضعیت: {(_isBorrowed ? $"امانت داده شده به {BorrowerName}" : "موجود")}");
    }
    
    public override decimal CalculateFine()
    {
        if (_isBorrowed && BorrowDate.HasValue)
        {
            int daysLate = (DateTime.Now - BorrowDate.Value).Days - 7; // مهلت ۷ روزه
            return daysLate > 0 ? daysLate * 500 : 0; // ۵۰۰ تومان در روز
        }
        return 0;
    }
}

// کلاس مدیریت کتابخانه
public class Library
{
    private List _items;
    
    public Library()
    {
        _items = new List();
    }
    
    public void AddItem(LibraryItem item)
    {
        _items.Add(item);
        Console.WriteLine($"آیتم {item.Title} به کتابخانه اضافه شد.");
    }
    
    public LibraryItem SearchByTitle(string title)
    {
        return _items.FirstOrDefault(item => 
            item.Title.Contains(title, StringComparison.OrdinalIgnoreCase));
    }
    
    public List SearchByAuthor(string author)
    {
        return _items.OfType()
                    .Where(book => book.Author.Contains(author, StringComparison.OrdinalIgnoreCase))
                    .Cast()
                    .ToList();
    }
    
    public void DisplayAllItems()
    {
        Console.WriteLine("\n=== فهرست کتابخانه ===");
        foreach (var item in _items)
        {
            item.DisplayInfo();
            Console.WriteLine("---");
        }
    }
    
    public void DisplayBorrowedItems()
    {
        Console.WriteLine("\n=== آیتم‌های امانت داده شده ===");
        var borrowedItems = _items.Where(item => item.IsBorrowed);
        foreach (var item in borrowedItems)
        {
            item.DisplayInfo();
            Console.WriteLine($"جریمه: {item.CalculateFine():C}");
            Console.WriteLine("---");
        }
    }
}

class Program
{
    static void Main()
    {
        Library library = new Library();
        
        // اضافه کردن آیتم‌ها
        library.AddItem(new Book("B001", "هری پاتر و سنگ جادو", 1997, "جی.کی. رولینگ", 320, "فانتزی"));
        library.AddItem(new Book("B002", "شازده کوچولو", 1943, "آنتوان دو سنت اگزوپری", 120, "ادبیات"));
        library.AddItem(new Magazine("M001", "مجله علم و فناوری", 2024, 150, "انتشارات علمی"));
        library.AddItem(new Magazine("M002", "مجله کامپیوتر", 2024, 75, "انتشارات فناوری"));
        
        // نمایش همه آیتم‌ها
        library.DisplayAllItems();
        
        // تست امانت
        var book1 = library.SearchByTitle("هری پاتر");
        book1?.Borrow("احمد محمدی");
        
        var magazine1 = library.SearchByTitle("علم و فناوری");
        magazine1?.Borrow("فاطمه احمدی");
        
        // نمایش آیتم‌های امانت داده شده
        library.DisplayBorrowedItems();
        
        // برگرداندن
        book1?.Return();
        
        Console.ReadKey();
    }
}

🏪 تمرین ۲: سیستم فروشگاه آنلاین

یک سیستم فروشگاه آنلاین طراحی کنید که شامل موارد زیر باشد:

  • کلاس پایه Product با ویژگی‌های نام، قیمت، موجودی و کد محصول
  • کلاس‌های Electronics، Clothing و Book که از Product ارث‌بری کنند
  • کلاس ShoppingCart برای مدیریت سبد خرید
  • کلاس Customer برای مدیریت اطلاعات مشتری
  • محاسبه تخفیف بر اساس نوع محصول و مشتری

جواب تمرین ۲: سیستم فروشگاه آنلاین

using System;
using System.Collections.Generic;
using System.Linq;

// کلاس پایه محصول
public abstract class Product
{
    protected string _productId;
    protected decimal _price;
    protected int _stock;
    
    public string Name { get; set; }
    public string ProductId { get { return _productId; } }
    public decimal Price { get { return _price; } }
    public int Stock { get { return _stock; } }
    public string Description { get; set; }
    
    public Product(string productId, string name, decimal price, int stock, string description)
    {
        _productId = productId;
        Name = name;
        _price = price;
        _stock = stock;
        Description = description;
    }
    
    // متد مجازی برای محاسبه تخفیف
    public virtual decimal CalculateDiscount(int quantity)
    {
        return 0; // بدون تخفیف پیش‌فرض
    }
    
    // متد انتزاعی برای نمایش اطلاعات
    public abstract void DisplayProductInfo();
    
    // متد کاهش موجودی
    public bool ReduceStock(int quantity)
    {
        if (_stock >= quantity)
        {
            _stock -= quantity;
            return true;
        }
        return false;
    }
    
    // متد افزایش موجودی
    public void AddStock(int quantity)
    {
        _stock += quantity;
    }
}

// کلاس محصولات الکترونیکی
public class Electronics : Product
{
    public string Brand { get; set; }
    public int WarrantyMonths { get; set; }
    public string Model { get; set; }
    
    public Electronics(string productId, string name, decimal price, int stock, string description, 
                      string brand, int warrantyMonths, string model) 
        : base(productId, name, price, stock, description)
    {
        Brand = brand;
        WarrantyMonths = warrantyMonths;
        Model = model;
    }
    
    public override decimal CalculateDiscount(int quantity)
    {
        // تخفیف ۵٪ برای خرید بیش از ۲ قطعه
        if (quantity >= 2)
            return 0.05m;
        return 0;
    }
    
    public override void DisplayProductInfo()
    {
        Console.WriteLine($"📱 محصول الکترونیکی: {Name}");
        Console.WriteLine($"برند: {Brand}, مدل: {Model}");
        Console.WriteLine($"قیمت: {_price:C}, موجودی: {_stock}");
        Console.WriteLine($"گارانتی: {WarrantyMonths} ماه");
        Console.WriteLine($"توضیحات: {Description}");
    }
}

// کلاس پوشاک
public class Clothing : Product
{
    public string Size { get; set; }
    public string Color { get; set; }
    public string Material { get; set; }
    
    public Clothing(string productId, string name, decimal price, int stock, string description,
                   string size, string color, string material) 
        : base(productId, name, price, stock, description)
    {
        Size = size;
        Color = color;
        Material = material;
    }
    
    public override decimal CalculateDiscount(int quantity)
    {
        // تخفیف ۱۰٪ برای خرید بیش از ۳ قطعه
        if (quantity >= 3)
            return 0.10m;
        return 0;
    }
    
    public override void DisplayProductInfo()
    {
        Console.WriteLine($"👕 پوشاک: {Name}");
        Console.WriteLine($"سایز: {Size}, رنگ: {Color}");
        Console.WriteLine($"جنس: {Material}");
        Console.WriteLine($"قیمت: {_price:C}, موجودی: {_stock}");
        Console.WriteLine($"توضیحات: {Description}");
    }
}

// کلاس کتاب
public class BookProduct : Product
{
    public string Author { get; set; }
    public string Publisher { get; set; }
    public int Pages { get; set; }
    
    public BookProduct(string productId, string name, decimal price, int stock, string description,
                      string author, string publisher, int pages) 
        : base(productId, name, price, stock, description)
    {
        Author = author;
        Publisher = publisher;
        Pages = pages;
    }
    
    public override decimal CalculateDiscount(int quantity)
    {
        // تخفیف ۱۵٪ برای خرید بیش از ۵ کتاب
        if (quantity >= 5)
            return 0.15m;
        return 0;
    }
    
    public override void DisplayProductInfo()
    {
        Console.WriteLine($"📚 کتاب: {Name}");
        Console.WriteLine($"نویسنده: {Author}");
        Console.WriteLine($"ناشر: {Publisher}, صفحات: {Pages}");
        Console.WriteLine($"قیمت: {_price:C}, موجودی: {_stock}");
        Console.WriteLine($"توضیحات: {Description}");
    }
}

// کلاس آیتم سبد خرید
public class CartItem
{
    public Product Product { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal Discount { get; set; }
    
    public decimal TotalPrice
    {
        get { return (UnitPrice * Quantity) * (1 - Discount); }
    }
    
    public CartItem(Product product, int quantity)
    {
        Product = product;
        Quantity = quantity;
        UnitPrice = product.Price;
        Discount = product.CalculateDiscount(quantity);
    }
}

// کلاس سبد خرید
public class ShoppingCart
{
    private List _items;
    
    public ShoppingCart()
    {
        _items = new List();
    }
    
    public bool AddItem(Product product, int quantity)
    {
        if (product.Stock >= quantity)
        {
            var existingItem = _items.FirstOrDefault(item => item.Product.ProductId == product.ProductId);
            
            if (existingItem != null)
            {
                existingItem.Quantity += quantity;
                existingItem.Discount = product.CalculateDiscount(existingItem.Quantity);
            }
            else
            {
                _items.Add(new CartItem(product, quantity));
            }
            
            Console.WriteLine($"{quantity} عدد {product.Name} به سبد خرید اضافه شد.");
            return true;
        }
        else
        {
            Console.WriteLine($"موجودی کافی نیست! فقط {product.Stock} عدد موجود است.");
            return false;
        }
    }
    
    public void RemoveItem(string productId)
    {
        var item = _items.FirstOrDefault(i => i.Product.ProductId == productId);
        if (item != null)
        {
            _items.Remove(item);
            Console.WriteLine($"{item.Product.Name} از سبد خرید حذف شد.");
        }
    }
    
    public decimal GetTotalAmount()
    {
        return _items.Sum(item => item.TotalPrice);
    }
    
    public void DisplayCart()
    {
        Console.WriteLine("\n=== سبد خرید ===");
        if (_items.Count == 0)
        {
            Console.WriteLine("سبد خرید خالی است.");
            return;
        }
        
        foreach (var item in _items)
        {
            Console.WriteLine($"{item.Product.Name} - تعداد: {item.Quantity}");
            Console.WriteLine($"قیمت واحد: {item.UnitPrice:C}");
            if (item.Discount > 0)
                Console.WriteLine($"تخفیف: {item.Discount:P}");
            Console.WriteLine($"قیمت کل: {item.TotalPrice:C}");
            Console.WriteLine("---");
        }
        
        Console.WriteLine($"مجموع کل: {GetTotalAmount():C}");
    }
    
    public bool Checkout()
    {
        foreach (var item in _items)
        {
            if (!item.Product.ReduceStock(item.Quantity))
            {
                Console.WriteLine($"خطا: موجودی {item.Product.Name} کافی نیست.");
                return false;
            }
        }
        
        Console.WriteLine("خرید با موفقیت انجام شد!");
        _items.Clear();
        return true;
    }
}

// کلاس مشتری
public class Customer
{
    public string CustomerId { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public ShoppingCart Cart { get; private set; }
    public bool IsPremium { get; set; }
    
    public Customer(string customerId, string name, string email, string phone)
    {
        CustomerId = customerId;
        Name = name;
        Email = email;
        Phone = phone;
        Cart = new ShoppingCart();
        IsPremium = false;
    }
    
    public void DisplayCustomerInfo()
    {
        Console.WriteLine($"\n=== اطلاعات مشتری ===");
        Console.WriteLine($"نام: {Name}");
        Console.WriteLine($"ایمیل: {Email}");
        Console.WriteLine($"تلفن: {Phone}");
        Console.WriteLine($"نوع عضویت: {(IsPremium ? "ویژه" : "عادی")}");
    }
}

class Program
{
    static void Main()
    {
        // ایجاد محصولات
        var laptop = new Electronics("E001", "لپ‌تاپ ایسوس", 25000000, 10, "لپ‌تاپ گیمینگ", "ASUS", 24, "ROG Strix");
        var shirt = new Clothing("C001", "پیراهن مردانه", 150000, 20, "پیراهن کتان", "L", "آبی", "کتان");
        var book = new BookProduct("B001", "آموزش C#", 80000, 15, "کتاب جامع برنامه‌نویسی", "احمد محمدی", "انتشارات فناوری", 450);
        
        // ایجاد مشتری
        var customer = new Customer("CUST001", "علی احمدی", "ali@example.com", "09123456789");
        customer.DisplayCustomerInfo();
        
        // نمایش محصولات
        Console.WriteLine("\n=== محصولات موجود ===");
        laptop.DisplayProductInfo();
        Console.WriteLine();
        shirt.DisplayProductInfo();
        Console.WriteLine();
        book.DisplayProductInfo();
        
        // اضافه کردن به سبد خرید
        customer.Cart.AddItem(laptop, 1);
        customer.Cart.AddItem(shirt, 3); // تخفیف ۱۰٪
        customer.Cart.AddItem(book, 5);  // تخفیف ۱۵٪
        
        // نمایش سبد خرید
        customer.Cart.DisplayCart();
        
        // تسویه حساب
        customer.Cart.Checkout();
        
        Console.ReadKey();
    }
}

💡 نکات مهم برای حل تمرین‌ها:

  • تجزیه مسئله: ابتدا مسئله را به بخش‌های کوچک‌تر تقسیم کنید
  • طراحی کلاس‌ها: روابط بین کلاس‌ها را مشخص کنید
  • کپسوله‌سازی: از فیلدهای private و ویژگی‌های public استفاده کنید
  • وراثت: کدهای مشترک را در کلاس پایه قرار دهید
  • چندریختی: از متدهای virtual و abstract استفاده کنید
  • تست تدریجی: هر بخش را جداگانه تست کنید
  • مستندسازی: کدهای خود را کامنت‌گذاری کنید