Inheritance در PHP یا وراثت و ارثبری یکی از مفاهیم اصلی برنامهنویسی شیگرا (OOP) است که به شما اجازه میدهد یک Class جدید را بر اساس یک Class موجود ایجاد کنید.
با استفاده از Inheritance میتوان ویژگیها و رفتارهای مشترک را در یک Class پایه قرار داد و سپس Classهای تخصصیتر را از آن ایجاد کرد.
برای مثال فرض کنید در یک سیستم فروشگاهی چند نوع کاربر داریم:
- مشتری
- فروشنده
- مدیر
- پشتیبان
ممکن است همه این کاربران ویژگیهایی مانند نام، ایمیل و متدهایی مانند ورود به سیستم داشته باشند، اما هر نوع کاربر رفتارهای اختصاصی خودش را نیز دارد.
در چنین شرایطی میتوان یک Class پایه به نام User ایجاد کرد و Classهای دیگر را از آن به ارث برد.
در این مقاله یاد میگیریم:
- Inheritance در PHP چیست؟
- Class والد و فرزند چه تفاوتی دارند؟
extendsچگونه کار میکند؟- چگونه Methodهای Class والد را Override کنیم؟
parentچیست؟- تفاوت
public،protectedوprivateدر وراثت چیست؟ - Constructor در Inheritance چگونه کار میکند؟
- چند مثال واقعی از Inheritance در PHP بررسی کنیم.
- چه زمانی استفاده از وراثت مناسب نیست؟
- Inheritance چه ارتباطی با Laravel و معماری نرمافزار دارد؟
# Inheritance در PHP چیست؟
Inheritance به زبان ساده یعنی یک Class بتواند ویژگیها و رفتارهای Class دیگری را دریافت کند.
Class اصلی را معمولاً:
Parent Class
یا:
Base Class
مینامیم.
Classی که از آن ارثبری میکند:
Child Class
یا:
Derived Class
نام دارد.
در PHP برای ایجاد وراثت از کلمه کلیدی:
extends
استفاده میشود.
یک مثال ساده:
class Animal
{
public function eat(): void
{
echo "Eating...";
}
}
class Cat extends Animal
{
}
در اینجا:
Animal
Class والد است.
و:
Cat
Class فرزند است.
بنابراین Cat میتواند از Methodهای قابل دسترسی Animal استفاده کند.
# استفاده از Method کلاس والد
اکنون میتوانیم از Class فرزند Object ایجاد کنیم:
$cat = new Cat();
$cat->eat();
خروجی:
Eating...
در حالی که Method eat() مستقیماً داخل Cat تعریف نشده است.
این Method از Class والد یعنی Animal به ارث رسیده است.
# چرا از Inheritance استفاده میکنیم؟
مهمترین دلیل استفاده از Inheritance، اشتراکگذاری رفتار و ویژگیهای مشترک بین Classها است.
فرض کنید چند نوع حساب بانکی داریم:
BankAccount
├── SavingsAccount
├── CurrentAccount
└── BusinessAccount
همه حسابها ممکن است ویژگیهایی مانند:
accountNumber
balance
deposit()
withdraw()
داشته باشند.
در این حالت میتوانیم ویژگیهای مشترک را داخل BankAccount قرار دهیم و Classهای تخصصیتر را از آن ایجاد کنیم.
# ساخت Class والد در PHP
مثلاً:
class User
{
public string $name;
public function login(): void
{
echo "User logged in.";
}
}
حالا یک Class فرزند ایجاد میکنیم:
class Admin extends User
{
}
اکنون Admin ویژگی و رفتارهای قابل دسترسی User را دارد.
$admin = new Admin();
$admin->name = 'Ali';
$admin->login();
# کلاس والد و کلاس فرزند چیست؟
برای درک بهتر:
class Vehicle
{
public function start(): void
{
echo "Vehicle started.";
}
}
class Car extends Vehicle
{
}
در این مثال:
| Class | نقش |
|---|---|
Vehicle | Parent / والد |
Car | Child / فرزند |
رابطه بین آنها به این صورت است:
Vehicle
↓
Car
یعنی Car یک نوع Vehicle محسوب میشود.
# کلمه کلیدی extends در PHP
برای ایجاد Inheritance باید از extends استفاده کنیم:
class Child extends Parent
{
}
مثلاً:
class Animal
{
public function move(): void
{
echo "Moving";
}
}
class Dog extends Animal
{
}
حالا:
$dog = new Dog();
$dog->move();
Method move() از Class Animal به ارث رسیده است.
# اضافه کردن Method جدید به Class فرزند
Class فرزند علاوه بر Methodهای والد میتواند Methodهای جدید خودش را داشته باشد.
مثلاً:
class Animal
{
public function eat(): void
{
echo "Eating";
}
}
class Dog extends Animal
{
public function bark(): void
{
echo "Woof!";
}
}
اکنون:
$dog = new Dog();
$dog->eat();
$dog->bark();
هر دو Method در دسترس هستند.
# Override در PHP چیست؟
یکی از قابلیتهای مهم Inheritance، Method Overriding است.
Override یعنی Class فرزند یک Method موجود در Class والد را با پیادهسازی خودش تعریف کند.
مثلاً:
class Animal
{
public function makeSound(): void
{
echo "Some sound";
}
}
class Dog extends Animal
{
public function makeSound(): void
{
echo "Woof!";
}
}
حالا:
$dog = new Dog();
$dog->makeSound();
خروجی:
Woof!
در اینجا Dog متد makeSound() مربوط به Animal را Override کرده است.
# چرا Override کاربرد دارد؟
فرض کنید یک سیستم پرداخت داریم.
تمام Gatewayهای پرداخت باید متدی به نام pay() داشته باشند، اما نحوه پرداخت هر Gateway متفاوت است.
مثلاً:
PaymentGateway
├── ZarinpalGateway
├── IDPayGateway
└── StripeGateway
هر Gateway میتواند رفتار مخصوص خودش را داشته باشد.
در این حالت Class پایه میتواند رفتار عمومی را تعریف کند و Classهای فرزند آن را تخصصیتر کنند.
# استفاده از parent در PHP
گاهی اوقات میخواهیم Method مربوط به Class والد را نیز اجرا کنیم.
برای این کار از:
parent
استفاده میکنیم.
مثلاً:
class User
{
public function login(): void
{
echo "Logging user...";
}
}
class Admin extends User
{
public function login(): void
{
parent::login();
echo " Logging admin...";
}
}
حالا:
$admin = new Admin();
$admin->login();
ابتدا Method والد اجرا میشود و سپس منطق مربوط به Admin اجرا خواهد شد.
# parent:: در PHP چیست؟
با parent:: میتوان به اعضای Class والد دسترسی پیدا کرد.
مثلاً:
parent::login();
برای اجرای Method والد.
یا در Constructor:
parent::__construct();
برای اجرای Constructor والد.
# Constructor و Inheritance در PHP
Constructor در وراثت نکته مهمی دارد.
مثلاً:
class User
{
public function __construct(
protected string $name
) {
}
}
class Admin extends User
{
}
هنگام ساخت Admin، Constructor والد نیز در صورت عدم تعریف Constructor در فرزند مورد استفاده قرار میگیرد.
$admin = new Admin('Ali');
اما اگر Class فرزند Constructor خودش را تعریف کند، برای اجرای Constructor والد باید در صورت نیاز به شکل صریح آن را فراخوانی کنیم:
class Admin extends User
{
public function __construct(
string $name,
private string $role
) {
parent::__construct($name);
}
}
در اینجا:
parent::__construct($name);
Constructor کلاس والد را اجرا میکند.
# protected در Inheritance
یکی از مهمترین Visibilityها در وراثت protected است.
فرض کنید:
class User
{
protected string $name;
public function setName(string $name): void
{
$this->name = $name;
}
}
class Admin extends User
{
public function showName(): void
{
echo $this->name;
}
}
چون name به صورت protected تعریف شده، Class فرزند میتواند به آن دسترسی داشته باشد.
اما از خارج Class نمیتوان مستقیماً به آن دسترسی داشت:
$admin->name;
این کد مجاز نیست.
# تفاوت public، protected و private در Inheritance
در زمان استفاده از Inheritance باید تفاوت Visibilityها را به خوبی بدانید.
| Visibility | داخل Class | Class فرزند | خارج Class |
|---|---|---|---|
public | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ❌ |
private | ✅ | ❌ | ❌ |
بنابراین اگر Property یا Methodی قرار است توسط Classهای فرزند استفاده شود، معمولاً protected یکی از گزینههاست.
البته بهتر است قبل از استفاده از protected بررسی کنید آیا میتوان طراحی را با API عمومی، Composition یا روش مناسب دیگری انجام داد.
# private در Inheritance
Property یا Method با Visibility private فقط متعلق به همان Class است.
مثلاً:
class User
{
private string $password;
public function setPassword(string $password): void
{
$this->password = $password;
}
}
class Admin extends User
{
public function test(): void
{
// Cannot directly access $password
}
}
Class Admin نمیتواند مستقیماً به $password دسترسی داشته باشد.
# آیا Class فرزند میتواند Property والد را Override کند؟
موضوع Propertyها با Methodها تفاوت دارد و محدودیتهای خاص خودش را دارد.
به طور کلی بهتر است از تعریف مجدد Propertyهای inherited بدون دلیل مشخص خودداری کنید.
طراحی مناسبتر این است که State مشترک در Class پایه و State اختصاصی در Class فرزند قرار گیرد.
مثلاً:
class User
{
protected string $name;
}
class Admin extends User
{
private string $role;
}
در اینجا:
User
└── name
Admin
└── role
ساختار واضحتری داریم.
# چند سطح Inheritance در PHP
در PHP میتوان زنجیرهای از Inheritance ایجاد کرد.
مثلاً:
Animal
↓
Mammal
↓
Dog
کد:
class Animal
{
public function eat(): void
{
echo "Eating";
}
}
class Mammal extends Animal
{
public function breathe(): void
{
echo "Breathing";
}
}
class Dog extends Mammal
{
public function bark(): void
{
echo "Barking";
}
}
اکنون:
$dog = new Dog();
$dog->eat();
$dog->breathe();
$dog->bark();
هر سه Method قابل استفاده هستند.
# آیا PHP از Multiple Inheritance پشتیبانی میکند؟
خیر.
PHP اجازه نمیدهد یک Class مستقیماً از چند Class مختلف extends کند.
مثلاً این ساختار مجاز نیست:
class Child extends ParentA, ParentB
{
}
در عوض PHP ابزارهایی مانند Interface و Trait را برای اشتراکگذاری قراردادها و رفتارها در اختیار برنامهنویس قرار میدهد.
برای مثال:
class User implements Authenticatable, Loggable
{
}
و یا:
class User
{
use HasRoles, HasPermissions;
}
این موضوع یکی از دلایلی است که باید Inheritance، Interface و Trait را به عنوان مفاهیم جداگانه یاد بگیرید.
# Inheritance و Interface چه تفاوتی دارند؟
Inheritance معمولاً یک رابطه:
is-a
را مدل میکند.
مثلاً:
Dog is an Animal
بنابراین:
class Dog extends Animal
{
}
اما Interface بیشتر یک قرارداد یا Contract را تعریف میکند.
مثلاً:
interface PaymentGateway
{
public function pay(float $amount): bool;
}
و:
class ZarinpalGateway implements PaymentGateway
{
public function pay(float $amount): bool
{
return true;
}
}
در اینجا Interface مشخص میکند Class باید چه رفتارهایی داشته باشد.
# Inheritance و Composition چه تفاوتی دارند؟
یکی از موضوعات مهم در طراحی Object-Oriented این است که همیشه نباید برای اشتراکگذاری رفتار از Inheritance استفاده کنیم.
در بسیاری از طراحیها:
Composition over Inheritance
رویکرد مناسبی است.
فرض کنید:
Order
PaymentService
NotificationService
به جای اینکه Order را از PaymentService به ارث ببریم، بهتر است Dependency را به آن تزریق کنیم:
class OrderService
{
public function __construct(
private PaymentService $paymentService
) {
}
}
اینجا OrderService یک PaymentService دارد، نه اینکه PaymentService باشد.
# چه زمانی از Inheritance استفاده کنیم؟
Inheritance زمانی مناسب است که بین دو Class رابطه واقعی و منطقی وجود داشته باشد.
مثلاً:
Animal → Dog
Vehicle → Car
User → Admin
Payment → OnlinePayment
در این موارد Class فرزند واقعاً نوعی از Class والد است.
# چه زمانی از Inheritance استفاده نکنیم؟
اگر فقط به دنبال استفاده مجدد از چند Method هستید، لزوماً Inheritance بهترین انتخاب نیست.
مثلاً اگر دو Class فقط یک Method مشترک دارند، ایجاد یک Parent Class صرفاً برای اشتراک آن Method ممکن است طراحی مناسبی نباشد.
در چنین شرایطی میتوان از:
- Composition
- Interface
- Trait
- Service
- Dependency Injection
استفاده کرد.
# مثال واقعی؛ سیستم کاربران
فرض کنید یک Application داریم که سه نوع کاربر دارد:
User
├── Customer
├── Admin
└── Vendor
Class پایه:
class User
{
public function __construct(
protected string $name,
protected string $email
) {
}
public function login(): void
{
echo "User logged in.";
}
}
Customer:
class Customer extends User
{
public function buyProduct(): void
{
echo "Product purchased.";
}
}
Vendor:
class Vendor extends User
{
public function addProduct(): void
{
echo "Product added.";
}
}
Admin:
class Admin extends User
{
public function deleteUser(): void
{
echo "User deleted.";
}
}
اکنون:
$customer = new Customer(
'Ali',
'ali@example.com'
);
$vendor = new Vendor(
'Reza',
'reza@example.com'
);
$admin = new Admin(
'Sara',
'sara@example.com'
);
هر سه کاربر رفتار مشترک login() را دارند، اما هرکدام رفتار اختصاصی خودشان را نیز دارند.
# مثال واقعی؛ سیستم پرداخت
یک نمونه کاربردیتر برای پروژههای واقعی:
abstract class Payment
{
public function __construct(
protected float $amount
) {
}
abstract public function pay(): bool;
}
حالا Gatewayهای مختلف:
class OnlinePayment extends Payment
{
public function pay(): bool
{
echo "Processing online payment...";
return true;
}
}
و:
class WalletPayment extends Payment
{
public function pay(): bool
{
echo "Processing wallet payment...";
return true;
}
}
استفاده:
$payment = new OnlinePayment(500000);
$payment->pay();
در این مثال علاوه بر Inheritance، مفهوم Abstract Class نیز وجود دارد که در مقاله جداگانهای بررسی خواهد شد.
# Inheritance در Laravel
اگر با Laravel کار میکنید، مرتب با Classهایی مواجه خواهید شد که از Classهای دیگر ارثبری میکنند.
مثلاً Controllerهای Laravel میتوانند از Controller پایه پروژه استفاده کنند:
class ProductController extends Controller
{
}
یا Exceptionهای اختصاصی میتوانند از Exceptionهای پایه PHP یا Framework استفاده کنند.
همچنین در Laravel و اکوسیستم PHP با ساختارهایی مانند:
Model
Controller
Exception
FormRequest
Job
Notification
Command
زیاد سروکار خواهید داشت.
بنابراین درک صحیح Inheritance برای کار با Laravel اهمیت زیادی دارد.
# Inheritance در Eloquent
در Laravel معمولاً مدلهای Eloquent از کلاس پایه Model استفاده میکنند:
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
}
در اینجا Product از قابلیتهای Class پایه Model استفاده میکند.
این قابلیتها شامل بخشهای مختلفی از رفتارهای Eloquent هستند و باعث میشوند Model شما بتواند با Database کار کند.
# Inheritance و Method Overriding در Laravel
در بعضی شرایط ممکن است بخواهید رفتار متدی را در Class فرزند تغییر دهید.
مثلاً:
class BaseService
{
public function execute(): void
{
echo "Base execution";
}
}
class ProductService extends BaseService
{
public function execute(): void
{
echo "Product execution";
}
}
اکنون:
$service = new ProductService();
$service->execute();
رفتار مربوط به ProductService اجرا میشود.
البته در Laravel بهتر است Override را با هدف مشخص انجام دهید و از ایجاد زنجیرههای پیچیده Inheritance پرهیز کنید.
# Inheritance و Polymorphism
Inheritance ارتباط نزدیکی با مفهوم Polymorphism دارد.
فرض کنید:
class Animal
{
public function makeSound(): void
{
}
}
class Dog extends Animal
{
public function makeSound(): void
{
echo "Woof";
}
}
class Cat extends Animal
{
public function makeSound(): void
{
echo "Meow";
}
}
اکنون میتوانیم Objectهای مختلف را به عنوان Animal در نظر بگیریم:
$animals = [
new Dog(),
new Cat(),
];
foreach ($animals as $animal) {
$animal->makeSound();
}
خروجی:
Woof
Meow
هر Object رفتار مخصوص خودش را دارد.
این مفهوم در طراحی سیستمهای قابل توسعه بسیار مهم است.
# مزایا و معایب Inheritance در PHP
مزایا
Inheritance میتواند باعث:
- کاهش تکرار کد
- اشتراک رفتار
- سازماندهی بهتر Classها
- توسعهپذیری
- ایجاد روابط منطقی بین Objectها
شود.
معایب
اما استفاده بیش از حد میتواند:
- وابستگی شدید بین Classها ایجاد کند.
- تغییر Class والد را به فرزندان تحمیل کند.
- ساختار پروژه را پیچیده کند.
- تست کردن بعضی بخشها را دشوارتر کند.
- Hierarchyهای بزرگ و غیرقابل مدیریت ایجاد کند.
به همین دلیل Inheritance باید بر اساس رابطه واقعی بین Domainها استفاده شود، نه صرفاً برای جلوگیری از تکرار چند خط کد.
# اشتباهات رایج در استفاده از Inheritance
۱. استفاده از Inheritance فقط برای Reuse کردن کد
اگر رابطه منطقی بین دو Class وجود ندارد، صرفاً اشتراک کد دلیل خوبی برای Inheritance نیست.
۲. ایجاد Hierarchyهای بسیار عمیق
ساختارهایی مانند:
A
↓
B
↓
C
↓
D
↓
E
میتواند نگهداری Application را سخت کند.
۳. استفاده بیش از حد از protected
اگر Class فرزند برای کارکرد صحیح خود مجبور باشد به تعداد زیادی Property داخلی والد دسترسی داشته باشد، ممکن است طراحی نیاز به بازنگری داشته باشد.
۴. Override کردن بدون توجه به قرارداد والد
Method فرزند باید رفتاری سازگار با انتظارات Class والد داشته باشد.
# بهترین روش استفاده از Inheritance
برای استفاده صحیح از وراثت در PHP این نکات را در نظر بگیرید:
رابطه واقعی ایجاد کنید
از خودتان بپرسید:
> آیا Child واقعاً یک نوع Parent است؟
اگر پاسخ منفی است، Composition احتمالاً انتخاب بهتری است.
Parent را کوچک نگه دارید
Class والد نباید مسئولیتهای بسیار زیادی داشته باشد.
از Abstraction استفاده کنید
در سیستمهای بزرگ استفاده از Interface و Abstract Class میتواند طراحی را منعطفتر کند.
Dependency Injection را جدی بگیرید
وابستگیهای Class را بهتر است به شکل واضح مدیریت کنید.
از Inheritance عمیق خودداری کنید
Hierarchy سادهتر معمولاً قابل نگهداریتر است.
# جمعبندی Inheritance در PHP
Inheritance در PHP یکی از مفاهیم اصلی OOP است که امکان ایجاد Classهای جدید بر اساس Classهای موجود را فراهم میکند.
برای ایجاد وراثت از:
extends
استفاده میکنیم.
Class اصلی را Parent و Class جدید را Child مینامیم.
Class فرزند میتواند رفتارهای قابل دسترسی والد را استفاده کند و در صورت نیاز Methodهای آن را Override کند.
برای دسترسی به اعضای Class والد نیز میتوان از:
parent::
استفاده کرد.
همچنین Visibilityهایی مانند:
public
protected
private
نقش مهمی در تعیین نحوه دسترسی Class فرزند به اعضای والد دارند.
با این حال، Inheritance ابزاری نیست که باید در همه جا استفاده شود. در طراحی حرفهای PHP و Laravel باید تفاوت بین Inheritance، Composition، Interface و Trait را بدانید و برای هر مسئله مناسبترین روش را انتخاب کنید.
در مقاله بعدی از این مجموعه، سراغ یکی از مهمترین مفاهیم مرتبط با OOP یعنی Interface در PHP خواهیم رفت و یاد میگیریم چگونه با Interfaceها قراردادهای قابل توسعه برای Classهای مختلف تعریف کنیم.
# سوالات متداول Inheritance در PHP
Inheritance در PHP چیست؟
Inheritance یا وراثت قابلیتی در برنامهنویسی شیگرا است که به یک Class اجازه میدهد ویژگیها و رفتارهای قابل دسترسی Class دیگری را به ارث ببرد.
چگونه در PHP ارثبری انجام دهیم؟
با استفاده از کلمه کلیدی extends:
class Dog extends Animal
{
}
Parent Class در PHP چیست؟
Class والد یا Parent Class، کلاسی است که Class دیگری از آن ارثبری میکند.
Child Class در PHP چیست؟
Child Class یا Class فرزند، کلاسی است که با استفاده از extends از Class والد ارثبری میکند.
Override در PHP چیست؟
Override یعنی Class فرزند یک Method موجود در Class والد را با پیادهسازی جدید خودش تعریف کند.
parent:: در PHP چه کاربردی دارد؟
از parent:: برای دسترسی به Methodها یا Constructor مربوط به Class والد استفاده میشود.
آیا PHP از Multiple Inheritance پشتیبانی میکند؟
خیر. یک Class در PHP نمیتواند مستقیماً از چند Class مختلف ارثبری کند. برای برخی سناریوهای مشابه میتوان از Interface و Trait استفاده کرد.
protected در Inheritance چه کاربردی دارد؟
اعضای protected داخل Class اصلی و Classهای فرزند قابل دسترسی هستند، اما از خارج Class قابل دسترسی مستقیم نیستند.
تفاوت Inheritance و Composition چیست؟
در Inheritance یک Class نوعی از Class دیگر است؛ در Composition یک Class از Object یا Dependency دیگری استفاده میکند. در بسیاری از طراحیهای مدرن، Composition میتواند نسبت به Inheritance انعطاف بیشتری داشته باشد.
آیا Inheritance در Laravel استفاده میشود؟
بله. Laravel و اکوسیستم PHP از Classهای پایه و ساختارهای مبتنی بر Inheritance استفاده میکنند و در بخشهایی مانند Modelها، Controllerها، Exceptionها و سایر اجزای Framework با این مفهوم مواجه خواهید شد.
# مقالات مرتبط
برای تقویت لینکسازی داخلی این مقاله، لینکهای زیر را در بخشهای مرتبط قرار دهید:
- OOP در PHP → مقاله مادر مفاهیم شیگرایی
- Class و Object در PHP → مقاله قبلی
- Interface در PHP → مقاله بعدی
- Trait در PHP
- Abstract Class در PHP
- Dependency Injection در PHP
- SOLID در PHP
- Design Pattern در PHP
- Namespace در PHP
- Autoload در PHP
- آموزش Composer
همچنین در ابتدای مقاله یا بخش جمعبندی، یک لینک طبیعی به Pillar اصلی آموزش برنامه نویسی وب و PHP قرار دهید.





