// استفاده
BankAccount acc = new BankAccount();
acc.Balance = 1000; // set اجرا میشود
Console.WriteLine(acc.Balance); // get اجرا میشود (1000)
acc.Balance = -500; // خطا میدهد و مقدار قبلی باقی میماند
Property ساده (Auto-Implemented Property):
csharp
class Product
{
public string Name { get; set; } // خودکار
public double Price { get; set; } // خودکار
public int Stock { get; set; }
}
// استفاده
Product p = new Product();
p.Name = "Laptop";
p.Price = 15000000;
p.Stock = 10;
---
⏱️ قسمت 7: سطح دسترسی (Access Modifiers)
سطح دسترسی معنی
public همه جا قابل دسترس است
private فقط داخل همان کلاس قابل دسترس است
protected داخل کلاس و کلاسهای فرزند
internal داخل همان پروژه
csharp
class Example
{
public int publicField = 1; // همه میبینند
private int privateField = 2; // فقط داخل Example
protected int protectedField = 3; // Example و کلاسهای ارثبر
internal int internalField = 4; // داخل همین پروژه
public void ShowPrivate()
{
Console.WriteLine(privateField); // ✅ داخل کلاس میشود
}
}
// در Main:
Example ex = new Example();
ex.publicField = 10; // ✅
// ex.privateField = 20; // ❌ خطا
ex.ShowPrivate(); // ✅ از طریق متد عمومی
---
⏱️ قسمت 8: مثال کامل – کلاس Student
csharp
class Student
{
// فیلدهای خصوصی
private string name;
private int age;
private double[] scores;
// سازنده
public Student(string studentName, int studentAge)
{
name = studentName;
age = studentAge;
scores = new double[0];
Console.WriteLine($"Student {name} created");
}
// Property
public string Name
{
get { return name; }
set { name = value; }
}
public int Age
{
get { return age; }
set
{
if (value >= 0 && value <= 120)
age = value;
else
Console.WriteLine("Invalid age!");
}
}
// متدها
public void AddScore(double score)
{
double[] newScores = new double[scores.Length + 1];
for (int i = 0; i < scores.Length; i++)
{
newScores[i] = scores[i];
}
newScores[scores.Length] = score;
scores = newScores;
}
public double GetAverage()
{
if (scores.Length == 0)
return 0;
double sum = 0;
foreach (double s in scores)
{
sum += s;
}
return sum / scores.Length;
}
public void ShowInfo()
{
Console.WriteLine($"Student: {name}, Age: {age}");
Console.WriteLine($"Average score: {GetAverage():F2}");
}
}
// استفاده در Main
Student s = new Student("Mohammad", 20);
s.AddScore(18);
s.AddScore(19);
s.AddScore(17.5);
s.ShowInfo();
---
✅ تمرین نهایی درس هشتم
برنامهای بنویسید که یک کلاس BankAccount بسازد با مشخصات زیر:
· فیلدهای خصوصی: accountNumber، balance، ownerName
· سازنده برای مقداردهی اولیه
· Property برای خواندن شماره حساب و موجودی (بدون set)
· Property برای نام صاحب حساب (get و set)
· متد Deposit(double amount) – افزایش موجودی
· متد Withdraw(double amount) – کاهش موجودی (اگر موجودی کافی نباشد خطا بدهد)
· متد ShowInfo() – نمایش اطلاعات
csharp
class BankAccount
{
private string accountNumber;
private double balance;
private string ownerName;
public BankAccount(string number, string owner, double initialBalance)
{
accountNumber = number;
ownerName = owner;
balance = (initialBalance >= 0) ? initialBalance : 0;
}
public string AccountNumber
{
get { return accountNumber; }
}
public double Balance
{
get { return balance; }
}
public string OwnerName
{
get { return ownerName; }
set { ownerName = value; }
}
public void Deposit(double amount)
{
if (amount > 0)
{
balance += amount;
Console.WriteLine($"Deposited: {amount:C}");
}
else
{
Console.WriteLine("Invalid deposit amount!");
}
}
public void Withdraw(double amount)
{
if (amount > 0 && amount <= balance)
{
balance -= amount;
Console.WriteLine($"Withdrawn: {amount:C}");
}
else if (amount > balance)
{
Console.WriteLine("Insufficient balance!");
}
else
{
Console.WriteLine("Invalid withdraw amount!");
}
}
public void ShowInfo()
{
Console.WriteLine($"Account: {accountNumber}");
Console.WriteLine($"Owner: {ownerName}");
Console.WriteLine($"Balance: {balance:C}");
}
}
// برنامه اصلی
class Program
{
static void Main()
{
BankAccount myAccount = new BankAccount("IR123456789", "Ali Rezaei", 1000000);
myAccount.ShowInfo();
Console.WriteLine();
myAccount.Deposit(500000);
myAccount.Withdraw(300000);
myAccount.Withdraw(2000000); // موجودی کافی نیست
Console.WriteLine();
myAccount.ShowInfo();
Console.WriteLine("\nPress Enter to exit...");
Console.ReadLine();
}
}
`--- 📌 جمعبندی درس هشتم مفهوم مثال تعریف کلاس class Car { ... } ساختن شیء Car myCar = new Car(); فیلد public string color; متد public void Start() { ... } سازنده public Car() { ... } Property public string Color { get; set; } public همه جا قابل دسترس private فقط داخل همان کلاس --- 🧪 تمرین برای شما 1. یک کلاس Book بسازید با: عنوان، نویسنده، قیمت، تعداد صفحات 2. یک کلاس Rectangle بسازید با: طول، عرض، و متدهای مساحت و محیط 3. یک کلاس Clock بسازید که زمان را نگه دارد و متد Tick() هر بار یک ثانیه اضافه کند --- اگر این درس را کامل فهمیدید، بگویید تا درس نهم (ارثبری و polymorphism) را شروع کنیم. سوالی بود بپرسید.
خیلی خوب، رسیدیم به درس نهم: ارثبری (Inheritance) و چندریختی (Polymorphism).
این درس شما را وارد دنیای حرفهای شیءگرایی میکند.
یک پروژه جدید بسازید (dotnet new console) و کدها را همراه من بنویسید و اجرا کنید.
---
📘 درس نهم – ارثبری و چندریختی
🎯 سرفصلها:
1. ارثبری چیست؟ (پدر و فرزند)
2. کلمه کلیدی : و base
3. بازنویسی متدها با virtual و override
4. کلاسهای مشتق شده (Derived Classes)
5. چندریختی (Polymorphism)
6. کلاس abstract (چکیده)
7. کلمه کلیدی sealed
8. تمرین جامع
---
⏱️ قسمت 1: ارثبری چیست؟
ارثبری = یک کلاس میتواند ویژگیها و رفتارهای کلاس دیگر را به ارث ببرد.
کلاس پدر (Base Class) → کلاس فرزند (Derived Class)
مثال ساده:
csharp
// کلاس پدر (Base Class)
class Animal
{
public string Name { get; set; }
public void Eat()
{
Console.WriteLine($"{Name} is eating...");
}
}
// کلاس فرزند (Derived Class) - از Animal ارث میبرد
class Dog : Animal
{
public void Bark()
{
Console.WriteLine($"{Name} is barking: Woof! Woof!");
}
}
// استفاده
Dog myDog = new Dog();
myDog.Name = "Rex"; // از کلاس Animal
myDog.Eat(); // از کلاس Animal
myDog.Bark(); // از خودش
📌 نکته: فرزند همه چیز پدر را دارد (به جز سازندههای خصوصی).
---
⏱️ قسمت 2: کلمه کلیدی base
از base برای دسترسی به اعضای کلاس پدر استفاده میشود.
csharp
class Vehicle
{
public string Brand { get; set; }
public Vehicle(string brand)
{
Brand = brand;
Console.WriteLine("Vehicle constructor called");
}
public void Start()
{
Console.WriteLine("Vehicle is starting...");
}
}
class Car : Vehicle
{
public string Model { get; set; }
// فراخوانی سازنده پدر با base
public Car(string brand, string model) : base(brand)
{
Model = model;
Console.WriteLine("Car constructor called");
}
public void ShowInfo()
{
base.Start(); // فراخوانی متد پدر
Console.WriteLine($"Brand: {Brand}, Model: {Model}");
}
}
// استفاده
Car myCar = new Car("BMW", "X5");
myCar.ShowInfo();
خروجی:
Vehicle constructor called
Car constructor called
Vehicle is starting...
Brand: BMW, Model: X5
---
⏱️ قسمت 3: بازنویسی متدها (virtual و override)
گاهی فرزند میخواهد رفتار پدر را تغییر دهد.
کلیدواژه کاربرد
virtual متدی که میتوان در فرزند بازنویسی شود
override بازنویسی متد مجازی در فرزند
csharp
class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Animal makes a sound");
}
}
class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Dog barks: Woof! Woof!");
}
}
class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Cat meows: Meow! Meow!");
}
}
// استفاده
Animal a1 = new Animal();
Animal a2 = new Dog();
Animal a3 = new Cat();
a1.MakeSound(); // Animal makes a sound
a2.MakeSound(); // Dog barks: Woof! Woof!
a3.MakeSound(); // Cat meows: Meow! Meow!
---
⏱️ قسمت 4: چندریختی (Polymorphism)
چندریختی = یک اسم (نوع پدر)، چند شکل (رفتار فرزند)
`csharp class Shape { public virtual double GetArea() { return 0; } public virtual void Draw() { Console.WriteLine("Drawing a shape"); } } class Circle : Shape { public double Radius { get; set; } public Circle(double radius) { Radius = radius; } public override double GetArea() { return Math.PI * Radius * Radius; } public override void Draw() { Console.WriteLine($"Drawing a circle with radius {Radius}"); } } class Rectangle : Shape { public double Width { get; set; } public double Height { get; set; } public Rectangle(double width, double height) { Width = width; Height = height; } public override double GetArea() { return Width * Height; } public override void Draw() { Console.WriteLine($"Drawing a rectangle {Width}x{Height}"); } }
// چندریختی در عمل
Shape[] shapes = new Shape[3];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
shapes[2] = new Circle(3);
foreach (Shape shape in shapes)
{
shape.Draw();
Console.WriteLine($"Area: {shape.GetArea():F2}");
Console.WriteLine();
}
---
⏱️ قسمت 5: کلاس abstract (چکیده)
کلاس abstract = کلاسی که نمیتوان از آن شیء ساخت، فقط برای ارثبری است.
csharp
// کلاس abstract
abstract class Employee
{
public string Name { get; set; }
public int Id { get; set; }
public Employee(string name, int id)
{
Name = name;
Id = id;
}
// متد abstract - بدون بدنه، فرزند حتماً باید پیادهسازی کند
public abstract double CalculateSalary();
// متد معمولی
public void ShowInfo()
{
Console.WriteLine($"Employee: {Name} (ID: {Id})");
}
}
class FullTimeEmployee : Employee
{
public double MonthlySalary { get; set; }
public FullTimeEmployee(string name, int id, double salary) : base(name, id)
{
MonthlySalary = salary;
}
public override double CalculateSalary()
{
return MonthlySalary;
}
}
class PartTimeEmployee : Employee
{
public double HourlyRate { get; set; }
public int HoursWorked { get; set; }
public PartTimeEmployee(string name, int id, double rate, int hours) : base(name, id)
{
HourlyRate = rate;
HoursWorked = hours;
}
public override double CalculateSalary()
{
return HourlyRate * HoursWorked;
}
}
// استفاده
// Employee e = new Employee(); // ❌ خطا - نمیتوان از کلاس abstract شیء ساخت
FullTimeEmployee fte = new FullTimeEmployee("Ali", 101, 5000000);
PartTimeEmployee pte = new PartTimeEmployee("Sara", 102, 50000, 80);
fte.ShowInfo();
Console.WriteLine($"Salary: {fte.CalculateSalary()}");
pte.ShowInfo();
Console.WriteLine($"Salary: {pte.CalculateSalary()}");
---
⏱️ قسمت 6: کلاس sealed (مهر و موم شده)
کلاس sealed = کلاسی که نمیتوان از آن ارثبری کرد.
csharp
sealed class FinalClass
{
public void DoSomething()
{
Console.WriteLine("This class cannot be inherited");
}
}
// class Child : FinalClass { } // ❌ خطا - نمیتوان از sealed ارث برد
متد sealed: در کلاس فرزند، نمیتوان بیشتر از این بازنویسی کرد.
csharp
class Parent
{
public virtual void MyMethod()
{
Console.WriteLine("Parent");
}
}
class Child : Parent
{
public sealed override void MyMethod() // sealed در این سطح
{
Console.WriteLine("Child");
}
}
// class GrandChild : Child
// {
// public override void MyMethod() { } // ❌ خطا - متد sealed است
// }
---
⏱️ قسمت 7: مثال کامل – سیستم حیوانات
csharp
using System;
// کلاس abstract
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 virtual void Move()
{
Console.WriteLine($"{Name} is moving");
}
public void ShowInfo()
{
Console.WriteLine($"Name: {Name}, Age: {Age}");
MakeSound();
Move();
}
}
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} barks: Woof! Woof!");
}
public override void Move()
{
Console.WriteLine($"{Name} runs happily");
}
}
class Bird : Animal
{
public double WingSpan { get; set; }
public Bird(string name, int age, double wingSpan) : base(name, age)
{
WingSpan = wingSpan;
}
public override void MakeSound()
{
Console.WriteLine($"{Name} chirps: Tweet! Tweet!");
}
public override void Move()
{
Console.WriteLine($"{Name} flies with {WingSpan}m wingspan");
}
}
class Fish : Animal
{
public string WaterType { get; set; } // Fresh or Salt
public Fish(string name, int age, string waterType) : base(name, age)
{
WaterType = waterType;
}
public override void MakeSound()
{
Console.WriteLine($"{Name} makes bubble sounds...");
}
public override void Move()
{
Console.WriteLine($"{Name} swims in {WaterType} water");
}
}
// برنامه اصلی
class Program
{
static void Main()
{
Animal[] animals = new Animal[3];
animals[0] = new Dog("Rex", 3, "German Shepherd");
animals[1] = new Bird("Tweety", 1, 0.25);
animals[2] = new Fish("Nemo", 2, "Salt");
foreach (Animal animal in animals)
{
animal.ShowInfo();
Console.WriteLine();
}
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
---
✅ تمرین نهایی درس نهم
سیستمی برای محاسبه حقوق کارمندان طراحی کنید:
1. کلاس abstract Employee با:
· فیلدهای: Name, ID, BaseSalary
· متد abstract CalculateSalary()
2. کلاس Manager : Employee
· Bonus اضافی
· حقوق = BaseSalary + Bonus
3. کلاس SalesPerson : Employee
· Commission (درصد فروش)
· حقوق = BaseSalary + (Sales * Commission / 100)
4. چندریختی: لیستی از Employee بسازید و حقوق همه را محاسبه کنید
csharp
abstract class Employee
{
public string Name { get; set; }
public int ID { get; set; }
public double BaseSalary { get; set; }
public Employee(string name, int id, double baseSalary)
{
Name = name;
ID = id;
BaseSalary = baseSalary;
}
public abstract double CalculateSalary();
public void ShowInfo()
{
Console.WriteLine($"{Name} (ID: {ID})");
Console.WriteLine($"Base Salary: {BaseSalary:C}");
Console.WriteLine($"Total Salary: {CalculateSalary():C}");
}
}
class Manager : Employee
{
public double Bonus { get; set; }
public Manager(string name, int id, double baseSalary, double bonus)
: base(name, id, baseSalary)
{
Bonus = bonus;
}
public override double CalculateSalary()
{
return BaseSalary + Bonus;
}
}
class SalesPerson : Employee
{
public double SalesAmount { get; set; }
public double CommissionPercent { get; set; }
public SalesPerson(string name, int id, double baseSalary, double sales, double commission)
: base(name, id, baseSalary)
{
SalesAmount = sales;
CommissionPercent = commission;
}
public override double CalculateSalary()
{
return BaseSalary + (SalesAmount * CommissionPercent / 100);
}
}
// برنامه اصلی
class Program
{
static void Main()
{
Employee[] employees = new Employee[3];
employees[0] = new Manager("Ali Mohammadi", 101, 8000000, 2000000);
employees[1] = new SalesPerson("Sara Ahmadi", 102, 5000000, 10000000, 5);
employees[2] = new Manager("Reza Karimi", 103, 9000000, 3000000);
foreach (Employee emp in employees)
{
emp.ShowInfo();
Console.WriteLine();
}
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
`--- 📌 جمعبندی درس نهم مفهوم کلیدواژه توضیح ارثبری : class Dog : Animal دسترسی به پدر base base.Method() متد قابل بازنویسی virtual public virtual void Method() بازنویسی متد override public override void Method() کلاس چکیده abstract abstract class MyClass متد چکیده abstract public abstract void Method(); غیرقابل ارثبری sealed sealed class MyClass --- 🧪 تمرین برای شما 1. کلاس Shape abstract بسازید با متدهای GetArea() و GetPerimeter() 2. کلاسهای Square، Triangle، Circle را بسازید 3. آرایهای از Shape بسازید و مساحت همه را محاسبه کنید --- اگر این درس را کامل فهمیدید، بگویید تا درس دهم (اینترفیسها) را شروع کنیم. سوالی بود بپرسید.
خیلی خوب، رسیدیم به درس دهم: اینترفیسها (Interface).
اینترفیس یکی از قدرتمندترین مفاهیم در سیشارپ است که به شما اجازه میدهد قراردادهای مشخصی بین کلاسها تعریف کنید.
یک پروژه جدید بسازید (dotnet new console) و کدها را همراه من بنویسید و اجرا کنید.
---
📘 درس دهم – اینترفیسها (Interface)
🎯 سرفصلها:
1. اینترفیس چیست؟
2. تفاوت اینترفیس با کلاس abstract
3. پیادهسازی اینترفیس
4. چندین اینترفیس در یک کلاس
5. اینترفیس به عنوان نوع داده
6. متدهای پیشفرض در اینترفیس (C# 8.0)
7. تمرین جامع
---
⏱️ قسمت 1: اینترفیس چیست؟
اینترفیس = یک قرارداد (Contract) که مشخص میکند کلاس چه کارهایی باید انجام دهد، اما نه چگونگی انجام آن.
csharp
// تعریف اینترفیس
interface IAnimal
{
void MakeSound(); // فقط تعریف، بدون بدنه
void Move();
}
// پیادهسازی اینترفیس در کلاس
class Dog : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Woof! Woof!");
}
public void Move()
{
Console.WriteLine("Dog is running");
}
}
class Cat : IAnimal
{
public void MakeSound()
{
Console.WriteLine("Meow! Meow!");
}
public void Move()
{
Console.WriteLine("Cat is walking silently");
}
}
// استفاده
IAnimal myDog = new Dog();
IAnimal myCat = new Cat();
myDog.MakeSound(); // Woof! Woof!
myCat.MakeSound(); // Meow! Meow!
📌 قوانین اینترفیس:
· فقط امضای متدها را تعریف میکند (بدون بدنه)
· نمیتواند فیلد داشته باشد
· کلاس میتواند چندین اینترفیس را پیادهسازی کند
· همه متدهای اینترفیس باید در کلاس پیادهسازی شوند
---
⏱️ قسمت 2: تفاوت اینترفیس با کلاس abstract
ویژگی اینترفیس (Interface) کلاس Abstract
تعداد در ارثبری چندین تا فقط یک کلاس
بدنه متدها ندارد (قبلاً) میتواند داشته باشد
فیلدها ندارد میتواند داشته باشد
سازنده ندارد میتواند داشته باشد
سطح دسترسی implicit public هر سطحی
کاربرد قرارداد پایه مشترک با بعضی پیادهسازیها
csharp
// اینترفیس: فقط قرارداد
interface IPrinter
{
void Print();
}
// کلاس abstract: میتواند پیادهسازی داشته باشد
abstract class Animal
{
public string Name { get; set; } // فیلد دارد
public abstract void MakeSound(); // بدون پیادهسازی
public void Sleep() // با پیادهسازی
{
Console.WriteLine("Sleeping...");
}
}
---
⏱️ قسمت 3: نامگذاری اینترفیسها
قاعده طلایی: نام اینترفیسها با I بزرگ شروع میشود.
csharp
interface IRepository // ✅ درست
interface ILogger // ✅ درست
interface IConvertible // ✅ درست
interface Printable // ❌ (بدون I)
interface IPrintable // ✅
---
⏱️ قسمت 4: پیادهسازی چندین اینترفیس
یک کلاس میتواند چندین اینترفیس را پیادهسازی کند.
csharp
interface IMovable
{
void Move();
}
interface ISpeakable
{
void Speak();
}
interface IFlyable
{
void Fly();
}
// کلاس میتواند چند اینترفیس داشته باشد
class Bird : IMovable, ISpeakable, IFlyable
{
public void Move()
{
Console.WriteLine("Bird is moving");
}
public void Speak()
{
Console.WriteLine("Bird is chirping");
}
public void Fly()
{
Console.WriteLine("Bird is flying");
}
}
// استفاده
Bird bird = new Bird();
bird.Move();
bird.Speak();
bird.Fly();
---
⏱️ قسمت 5: اینترفیس به عنوان نوع داده
میتوانیم از اینترفیس به عنوان نوع متغیر استفاده کنیم.
`csharp interface IShape { double GetArea(); double GetPerimeter(); } class Circle : IShape { public double Radius { get; set; } public Circle(double radius) { Radius = radius; } public double GetArea() { return Math.PI * Radius * Radius; } public double GetPerimeter() { return 2 * Math.PI * Radius; } } class Rectangle : IShape { public double Width { get; set; } public double Height { get; set; } public Rectangle(double width, double height) { Width = width; Height = height; } public double GetArea() { return Width * Height; } public double GetPerimeter() { return 2 * (Width + Height); } }
// چندریختی با اینترفیس
IShape[] shapes = new IShape[3];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
shapes[2] = new Circle(3);
foreach (IShape shape in shapes)
{
Console.WriteLine($"Area: {shape.GetArea():F2}");
Console.WriteLine($"Perimeter: {shape.GetPerimeter():F2}");
Console.WriteLine();
}
---
⏱️ قسمت 6: مثال واقعی – سیستم پرداخت
csharp
// اینترفیس پرداخت
interface IPayment
{
void Pay(decimal amount);
string GetPaymentMethod();
}
// پیادهسازی با کارت اعتباری
class CreditCardPayment : IPayment
{
public string CardNumber { get; set; }
public CreditCardPayment(string cardNumber)
{
CardNumber = cardNumber;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid {amount:C} using Credit Card ending with {CardNumber.Substring(CardNumber.Length - 4)}");
}
public string GetPaymentMethod()
{
return "Credit Card";
}
}
// پیادهسازی با پیپال
class PayPalPayment : IPayment
{
public string Email { get; set; }
public PayPalPayment(string email)
{
Email = email;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid {amount:C} using PayPal account {Email}");
}
public string GetPaymentMethod()
{
return "PayPal";
}
}
// پیادهسازی با ارز دیجیتال
class CryptoPayment : IPayment
{
public string WalletAddress { get; set; }
public CryptoPayment(string walletAddress)
{
WalletAddress = walletAddress;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid {amount:C} using Crypto wallet {WalletAddress.Substring(0, 6)}...");
}
public string GetPaymentMethod()
{
return "Cryptocurrency";
}
}
// سیستم پرداخت
class PaymentProcessor
{
public void ProcessPayment(IPayment payment, decimal amount)
{
Console.WriteLine($"Processing {payment.GetPaymentMethod()} payment...");
payment.Pay(amount);
Console.WriteLine("Payment completed!");
}
}
// استفاده
PaymentProcessor processor = new PaymentProcessor();
IPayment payment1 = new CreditCardPayment("1234-5678-9012-3456");
IPayment payment2 = new PayPalPayment("user@example.com");
IPayment payment3 = new CryptoPayment("1A2B3C4D5E6F");
processor.ProcessPayment(payment1, 150.50m);
Console.WriteLine();
processor.ProcessPayment(payment2, 75.25m);
Console.WriteLine();
processor.ProcessPayment(payment3, 200.00m);
---
⏱️ قسمت 7: متدهای پیشفرض در اینترفیس (C# 8.0+)
از C# 8.0 به بعد، میتوان در اینترفیس متد با بدنه (پیشفرض) داشت.
csharp
interface ILogger
{
void Log(string message); // باید پیادهسازی شود
// متد پیشفرض (اختیاری برای پیادهسازی)
void LogError(string error)
{
Console.WriteLine($"ERROR: {error}");
Log(error); // میتواند متد دیگر را صدا بزند
}
}
class FileLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"Writing to file: {message}");
}
// نیازی به پیادهسازی LogError نیست (پیشفرض دارد)
}
class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"Console: {message}");
}
// میتوان LogError را بازنویسی کرد
public void LogError(string error)
{
Console.WriteLine($"!!! CONSOLE ERROR: {error} !!!");
}
}
// استفاده
ILogger fileLog = new FileLogger();
ILogger consoleLog = new ConsoleLogger();
fileLog.LogError("File not found"); // از پیشفرض استفاده میکند
consoleLog.LogError("Network error"); // از پیادهسازی خودش استفاده میکند
---
✅ تمرین نهایی درس دهم
سیستم مدیریت کاربران با اینترفیس بسازید:
1. اینترفیس IUser با متدهای:
· string GetUsername()
· string GetRole()
· bool HasPermission(string permission)
2. کلاس Admin : IUser
3. کلاس RegularUser : IUser
4. کلاس Guest : IUser
csharp
using System;
using System.Collections.Generic;
interface IUser
{
string GetUsername();
string GetRole();
bool HasPermission(string permission);
}
class Admin : IUser
{
private string username;
public Admin(string name)
{
username = name;
}
public string GetUsername()
{
return username;
}
public string GetRole()
{
return "Administrator";
}
public bool HasPermission(string permission)
{
// ادمین به همه چیز دسترسی دارد
return true;
}
}
class RegularUser : IUser
{
private string username;
private List<string> permissions;
public RegularUser(string name)
{
username = name;
permissions = new List<string> { "read", "write_own" };
}
public string GetUsername()
{
return username;
}
public string GetRole()
{
return "Regular User";
}
public bool HasPermission(string permission)
{
return permissions.Contains(permission);
}
}
class Guest : IUser
{
public string GetUsername()
{
return "Guest";
}
public string GetRole()
{
return "Guest";
}
public bool HasPermission(string permission)
{
// مهمان فقط خواندن دارد
return permission == "read";
}
}
// سیستم مدیریت دسترسی
class AccessManager
{
public void CheckAccess(IUser user, string permission)
{
Console.WriteLine($"User: {user.GetUsername()} (Role: {user.GetRole()})");
Console.WriteLine($"Requested permission: {permission}");
if (user.HasPermission(permission))
{
Console.WriteLine("✅ ACCESS GRANTED");
}
else
{
Console.WriteLine("❌ ACCESS DENIED");
}
Console.WriteLine();
}
}
// برنامه اصلی
class Program
{
static void Main()
{
AccessManager manager = new AccessManager();
IUser[] users = new IUser[3];
users[0] = new Admin("Ali_Admin");
users[1] = new RegularUser("Sara_User");
users[2] = new Guest();
string[] permissions = { "read", "write", "delete", "write_own" };
foreach (IUser user in users)
{
Console.WriteLine($"=== Testing {user.GetUsername()} ===");
foreach (string perm in permissions)
{
manager.CheckAccess(user, perm);
}
}
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
`--- 📌 جمعبندی درس دهم مفهوم توضیح اینترفیس قراردادی که کلاس باید پیادهسازی کند نامگذاری با I شروع میشود (مثل IMovable) پیادهسازی کلاس : اینترفیس چند اینترفیس class MyClass : I1, I2, I3 متدهای پیشفرض از C# 8.0 به بعد میتوان بدنه داشت اینترفیس در مقابل کلاس Abstract: سناریو راه حل میخواهم چندین کلاس از یک پایه ارث ببرند کلاس Abstract میخواهم یک قرارداد مشخص کنم اینترفیس میخواهم یک کلاس چند نوع رفتار داشته باشد چندین اینترفیس میخواهم فیلد داشته باشم کلاس Abstract --- 🧪 تمرین برای شما 1. اینترفیس ICalculator بسازید با متدهای Add, Subtract, Multiply, Divide 2. دو کلاس BasicCalculator و ScientificCalculator آن را پیادهسازی کنند 3. اینترفیس IComparable را در کلاس Student پیادهسازی کنید و دانشجوها را بر اساس نمره مرتب کنید --- تبریک! 🎉 شما 10 درس اصلی سیشارپ را کامل کردید. درسهای پیشنهادی برای ادامه: · دهم: Delegates و Events · یازدهم: LINQ · دوازدهم: Exception Handling پیشرفته · سیزدهم: کار با فایلها · چهاردهم: Async/Await اگر سوالی دارید یا میخواهید درس بعدی را شروع کنید، بگویید. موفق باشید!
خیلی خوب، رسیدیم به درس یازدهم: کلاسهای استاتیک (Static) و نمونه (Instance).
این درس خیلی مهم است چون خیلی از برنامهنویسان تازهکار فرق بین static و غیر static را اشتباه میگیرند.
یک پروژه جدید بسازید (dotnet new console) و کدها را همراه من بنویسید و اجرا کنید.
---
📘 درس یازدهم – کلاسهای استاتیک و نمونه
🎯 سرفصلها:
1. تفاوت استاتیک و نمونه (Instance)
2. فیلد استاتیک
3. متد استاتیک
4. کلاس استاتیک
5. سازنده استاتیک
6. کلاس Math و Console مثال واقعی
7. تمرین جامع
---
⏱️ قسمت 1: تفاوت استاتیک و نمونه
تصور کنید کلاس یک قالب کلوچه است:
مفهوم توضیح
نمونه (Instance) هر کلوچه (با شکل و اندازه خودش)
استاتیک (Static) قالب کلوچه (یک نسخه مشترک بین همه)
csharp
class Cookie
{
// فیلد نمونه (هر کلوچه یک مقدار جدا دارد)
public string Shape { get; set; }
// فیلد استاتیک (بین همه کلوچهها مشترک است)
public static string MoldType = "Metal Mold";
}
// استفاده
Cookie cookie1 = new Cookie();
Cookie cookie2 = new Cookie();
cookie1.Shape = "Star";
cookie2.Shape = "Heart";
Console.WriteLine(cookie1.Shape); // Star
Console.WriteLine(cookie2.Shape); // Heart
// فیلد استاتیک: از طریق کلاس دسترسی داریم، نه نمونه
Console.WriteLine(Cookie.MoldType); // Metal Mold
📌 نکته طلایی:
· اعضای نمونه (Instance) به هر شیء تعلق دارند (هر کدام مقدار خودش را دارد)
· اعضای استاتیک (Static) به کلاس تعلق دارند (یک مقدار برای همه)
---
⏱️ قسمت 2: فیلد استاتیک
فیلدهای استاتیک بین همه نمونههای کلاس مشترک هستند.
csharp
class BankAccount
{
public string Owner { get; set; }
public double Balance { get; set; }
// فیلد استاتیک - تعداد کل حسابهای ساخته شده
public static int TotalAccounts = 0;
public BankAccount(string owner, double balance)
{
Owner = owner;
Balance = balance;
TotalAccounts++; // هر بار یک حساب ساخته میشود، این عدد زیاد میشود
}
}
// استفاده
BankAccount acc1 = new BankAccount("Ali", 1000);
BankAccount acc2 = new BankAccount("Sara", 2000);
BankAccount acc3 = new BankAccount("Reza", 1500);
Console.WriteLine($"Total accounts: {BankAccount.TotalAccounts}"); // 3
// ❌ acc1.TotalAccounts - نمیتوان از نمونه دسترسی داشت
---
⏱️ قسمت 3: متد استاتیک
متدهای استاتیک به کلاس تعلق دارند، نه به نمونه.
csharp
class MathHelper
{
// متد استاتیک - نیازی به ساختن شیء نیست
public static int Add(int a, int b)
{
return a + b;
}
public static int Multiply(int a, int b)
{
return a * b;
}
public static bool IsEven(int number)
{
return number % 2 == 0;
}
}
// استفاده - بدون ساختن شیء!
int sum = MathHelper.Add(5, 3);
int product = MathHelper.Multiply(4, 5);
bool even = MathHelper.IsEven(10);
Console.WriteLine($"Sum: {sum}"); // 8
Console.WriteLine($"Product: {product}"); // 20
Console.WriteLine($"Is 10 even? {even}"); // True
فرق متد استاتیک و نمونه:
csharp
class Calculator
{
// متد نمونه (Instance)
public int InstanceAdd(int a, int b)
{
return a + b;
}
// متد استاتیک (Static)
public static int StaticAdd(int a, int b)
{
return a + b;
}
}
// استفاده
Calculator calc = new Calculator(); // باید شیء بسازیم
int result1 = calc.InstanceAdd(5, 3); // ✅
int result2 = Calculator.StaticAdd(5, 3); // ✅ بدون ساختن شیء
// int result3 = calc.StaticAdd(5, 3); // ❌ نمیتوان از نمونه صدا زد
---
⏱️ قسمت 4: کلاس استاتیک
کلاس استاتیک = کلاسی که نمیتوان از آن شیء ساخت.
`csharp static class Utility { // فقط میتواند اعضای استاتیک داشته باشد public static double PI = 3.14159; public static double CircleArea(double radius) { return PI * radius * radius; } public static string ToTitleCase(string text) { if (string.IsNullOrEmpty(text)) return text; return char.ToUpper(text[0]) + text.Substring(1).ToLower(); } } // استفاده // Utility u = new Utility(); // ❌ خطا - نمیتوان از کلاس استاتیک شیء ساخت double area = Utility.CircleArea(5); string title = Utility.ToTitleCase("hello world");
Console.WriteLine($"Area: {area:F2}"); // 78.54
Console.WriteLine($"Title: {title}"); // Hello world
📌 قوانین کلاس استاتیک:
· نمیتوان از آن نمونه (Object) ساخت
· فقط میتواند اعضای استاتیک داشته باشد
· نمیتواند سازنده نمونه (instance constructor) داشته باشد
· به طور خودکار sealed است (نمیتوان از آن ارث برد)
---
⏱️ قسمت 5: سازنده استاتیک (Static Constructor)
سازنده استاتیک یک بار و قبل از اولین استفاده از کلاس اجرا میشود.
csharp
class Database
{
public static string ConnectionString;
public static int ConnectionCount;
// سازنده استاتیک - یک بار اجرا میشود
static Database()
{
Console.WriteLine("Static constructor called");
ConnectionString = "Server=localhost;Database=MyDB";
ConnectionCount = 0;
}
// متد استاتیک
public static void Connect()
{
ConnectionCount++;
Console.WriteLine($"Connected to {ConnectionString}");
Console.WriteLine($"Total connections: {ConnectionCount}");
}
}
// استفاده
Console.WriteLine("Before first use");
Database.Connect(); // اولین استفاده → سازنده استاتیک اجرا میشود
Database.Connect(); // سازنده استاتیک دیگر اجرا نمیشود
Database.Connect();
خروجی:
Before first use
Static constructor called
Connected to Server=localhost;Database=MyDB
Total connections: 1
Connected to Server=localhost;Database=MyDB
Total connections: 2
Connected to Server=localhost;Database=MyDB
Total connections: 3
---
⏱️ قسمت 6: مثال واقعی – کلاس Math و Console
کلاسهایی که روزانه استفاده میکنیم، استاتیک هستند:
csharp
// کلاس Math - کاملاً استاتیک
double max = Math.Max(10, 20); // 20
double min = Math.Min(10, 20); // 10
double sqrt = Math.Sqrt(25); // 5
double power = Math.Pow(2, 3); // 8
double pi = Math.PI; // 3.14159...
double abs = Math.Abs(-5); // 5
// کلاس Console - استاتیک
Console.WriteLine("Hello"); // چاپ
string input = Console.ReadLine(); // ورودی
// کلاس Convert - استاتیک
int num = Convert.ToInt32("123");
double d = Convert.ToDouble("3.14");
---
⏱️ قسمت 7: ترکیب استاتیک و نمونه
میتوانیم در یک کلاس هم عضو استاتیک و هم عضو نمونه داشته باشیم.
csharp
class Employee
{
// فیلدهای نمونه
public string Name { get; set; }
public int Id { get; set; }
public double Salary { get; set; }
// فیلد استاتیک
private static int nextId = 1000;
public static string CompanyName = "TechCorp";
public static int TotalEmployees = 0;
// سازنده نمونه
public Employee(string name, double salary)
{
Name = name;
Salary = salary;
Id = nextId++;
TotalEmployees++;
Console.WriteLine($"Employee {Name} created with ID {Id}");
}
// متد نمونه (میتواند به استاتیک دسترسی داشته باشد)
public void ShowInfo()
{
Console.WriteLine($"ID: {Id}, Name: {Name}, Salary: {Salary:C}");
Console.WriteLine($"Company: {Employee.CompanyName}");
Console.WriteLine($"Total employees: {Employee.TotalEmployees}");
}
// متد استاتیک (نمیتواند به اعضای نمونه دسترسی داشته باشد)
public static void ShowCompanyInfo()
{
Console.WriteLine($"Company: {CompanyName}");
Console.WriteLine($"Total employees: {TotalEmployees}");
// Console.WriteLine(Name); // ❌ خطا - Name عضو نمونه است
}
}
// استفاده
Employee emp1 = new Employee("Ali", 5000000);
Employee emp2 = new Employee("Sara", 6000000);
Employee emp3 = new Employee("Reza", 5500000);
Console.WriteLine();
emp1.ShowInfo();
Console.WriteLine();
Employee.ShowCompanyInfo();
---
⏱️ قسمت 8: متد استاتیک در کلاس غیر استاتیک
کلاس غیر استاتیک میتواند متد استاتیک داشته باشد.
csharp
class StringHelper
{
// متد استاتیک
public static string Reverse(string text)
{
char[] chars = text.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
public static int CountWords(string text)
{
if (string.IsNullOrEmpty(text))
return 0;
return text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
}
// متد نمونه
public string AddExclamation(string text)
{
return text + "!!!";
}
}
// استفاده
string reversed = StringHelper.Reverse("hello");
Console.WriteLine(reversed); // olleh
int wordCount = StringHelper.CountWords("Hello world from C#");
Console.WriteLine(wordCount); // 4
// برای متد نمونه باید شیء بسازیم
StringHelper helper = new StringHelper();
string excited = helper.AddExclamation("Hello");
Console.WriteLine(excited); // Hello!!!
---
✅ تمرین نهایی درس یازدهم
برنامهای بنویسید که:
1. کلاس Product با فیلدهای نمونه (Name, Price) و فیلد استاتیک (TotalProducts, TotalValue)
2. متد نمونه ShowInfo()
3. متد استاتیک ShowSummary()
4. هر بار یک محصول جدید ساخته شود، TotalProducts و TotalValue بهروز شود
csharp
using System;
class Product
{
// فیلدهای نمونه
public string Name { get; set; }
public double Price { get; set; }
// فیلدهای استاتیک
private static int totalProducts = 0;
private static double totalValue = 0;
// سازنده
public Product(string name, double price)
{
Name = name;
Price = price;
totalProducts++;
totalValue += price;
Console.WriteLine($"Product '{name}' created with price {price:C}");
}
// متد نمونه
public void ShowInfo()
{
Console.WriteLine($"Product: {Name}, Price: {Price:C}");
}
// متد استاتیک برای نمایش خلاصه
public static void ShowSummary()
{
Console.WriteLine("\n=== Store Summary ===");
Console.WriteLine($"Total Products: {totalProducts}");
Console.WriteLine($"Total Inventory Value: {totalValue:C}");
Console.WriteLine($"Average Price: {(totalProducts > 0 ? totalValue / totalProducts : 0):C}");
}
// متد استاتیک برای محاسبه تخفیف
public static double ApplyDiscount(double price, double discountPercent)
{
return price * (1 - discountPercent / 100);
}
}
class Program
{
static void Main()
{
// ساختن محصولات
Product p1 = new Product("Laptop", 15000000);
Product p2 = new Product("Mouse", 250000);
Product p3 = new Product("Keyboard", 850000);
Product p4 = new Product("Monitor", 5500000);
Console.WriteLine();
// نمایش اطلاعات هر محصول
p1.ShowInfo();
p2.ShowInfo();
p3.ShowInfo();
p4.ShowInfo();
// نمایش خلاصه فروشگاه
Product.ShowSummary();
// استفاده از متد استاتیک تخفیف
double discountedPrice = Product.ApplyDiscount(15000000, 15);
Console.WriteLine($"\nLaptop with 15% discount: {discountedPrice:C}");
Console.WriteLine("\nPress Enter to exit...");
Console.ReadLine();
}
}
---
📌 جمعبندی درس یازدهم
مفهوم مثال دسترسی
فیلد نمونه public string Name از طریق شیء
فیلد استاتیک public static int Count از طریق کلاس
متد نمونه public void Show() از طریق شیء
متد استاتیک public static void Calc() از طریق کلاس
کلاس استاتیک static class Utility نمیتوان شیء ساخت
قوانین مهم:
1. متد استاتیک نمیتواند به عضو نمونه دسترسی داشته باشد
csharp
static void Method() { Name = "Ali"; } // ❌ اگر Name نمونه باشد
2. متد نمونه میتواند به عضو استاتیک دسترسی داشته باشد
csharp
void Method() { Count = 10; } // ✅ اگر Count استاتیک باشد
`3. کلاس استاتیک فقط عضو استاتیک میتواند داشته باشد --- 🧪 تمرین برای شما 1. کلاس Counter بسازید با: · فیلد استاتیک totalCount
· متد استاتیک Increment()
· متد استاتیک GetCount()
· از چند جا صدا بزنید و نتیجه را ببینید
2. کلاس Configuration بسازید با:
· فیلدهای استاتیک: AppName, Version, Theme
· سازنده استاتیک برای مقداردهی اولیه
3. برنامهای بنویسید که تعداد دفعاتی که یک متد صدا زده شده را با فیلد استاتیک بشمارد
---
اگر این درس را کامل فهمیدید، بگویید تا درس دوازدهم (Enum و Struct) را شروع کنیم. سوالی بود بپرسید.