آموزش برنامه نویسی PHP-جلسه هفدهم

آموزش برنامه نویسی PHP-جلسه هفدهم

ویژگی ها ومتدها می توانند سطح دسترسی داشته باشند و به صورت های مختلف تعریف شوند.

Table of contents [Show] [Hide]

Access Modifiers در PHP چیست؟

در برنامه‌نویسی شی‌گرا (OOP) در PHP، یکی از مفاهیم مهم برای کنترل دسترسی به اطلاعات و رفتارهای داخل کلاس، Access Modifiers یا سطوح دسترسی است.

Access Modifier مشخص می‌کند که یک Property یا Method از کدام بخش‌های برنامه قابل دسترسی باشد. این قابلیت به ما کمک می‌کند اطلاعات حساس یک کلاس را از دسترسی مستقیم خارج کنیم و ساختار کد را بهتر مدیریت کنیم.

در PHP سه سطح دسترسی اصلی وجود دارد:

  • public یا عمومی
  • protected یا محافظت‌شده
  • private یا خصوصی

در ادامه هر یک از این سطوح دسترسی را به همراه مثال بررسی می‌کنیم و سپس به سراغ یکی از مهم‌ترین مفاهیم OOP یعنی Inheritance یا وراثت، بازنویسی متدها و کلمه کلیدی final می‌رویم.


Public در PHP چیست؟

public عمومی‌ترین سطح دسترسی در PHP است.

وقتی یک Property یا Method را به صورت public تعریف می‌کنیم، آن عضو از داخل همان کلاس، کلاس‌های فرزند و همچنین خارج از کلاس قابل دسترسی است.

برای مثال:

 
<?php

class Fruit
{
    public $name;
    public $color;
}

$mango = new Fruit();

$mango->name = "Mango";
$mango->color = "Yellow";

echo $mango->name;
echo $mango->color;

?>
 

در این مثال هر دو Property به صورت public تعریف شده‌اند، بنابراین از خارج کلاس نیز می‌توانیم به آنها دسترسی داشته باشیم.


Protected در PHP چیست؟

سطح دسترسی protected محدودتر از public است.

یک Property یا Method که به صورت protected تعریف شده باشد:

  • از داخل همان کلاس قابل دسترسی است.
  • از داخل کلاس‌های فرزند قابل دسترسی است.
  • از خارج کلاس و به صورت مستقیم از طریق Object قابل دسترسی نیست.

برای مثال:

 
<?php

class Fruit
{
    public $name;
    protected $color;
}

$mango = new Fruit();

$mango->name = "Mango";     // OK
$mango->color = "Yellow";   // Error

?>
 

در اینجا دسترسی به name مجاز است، چون public است؛ اما دسترسی مستقیم به color امکان‌پذیر نیست، چون protected تعریف شده است.


Protected در کلاس فرزند

یکی از کاربردهای مهم protected در زمان استفاده از Inheritance مشخص می‌شود.

فرض کنید کلاس Fruit یک Property محافظت‌شده داشته باشد و کلاس Strawberry از آن ارث‌بری کند:

 
<?php

class Fruit
{
    protected $color;
}

class Strawberry extends Fruit
{
    public function set_color($color)
    {
        $this->color = $color;
    }

    public function get_color()
    {
        return $this->color;
    }
}

$strawberry = new Strawberry();

$strawberry->set_color("Red");

echo $strawberry->get_color();

?>
 

در این مثال Object مربوط به Strawberry نمی‌تواند مستقیماً به $color دسترسی داشته باشد، اما متدهای داخل کلاس فرزند می‌توانند به آن دسترسی پیدا کنند.

این یکی از تفاوت‌های مهم protected با private است.


Private در PHP چیست؟

private محدودترین سطح دسترسی در بین سه Access Modifier اصلی PHP است.

وقتی یک Property یا Method را private تعریف می‌کنیم، دسترسی به آن فقط از داخل همان کلاسی که عضو در آن تعریف شده امکان‌پذیر است.

برای مثال:

 
<?php

class Fruit
{
    public $name;
    protected $color;
    private $weight;
}

$mango = new Fruit();

$mango->name = "Mango";      // OK
$mango->color = "Yellow";    // Error
$mango->weight = "300";      // Error

?>
 

در این مثال:

 
public $name;
 

از خارج کلاس قابل دسترسی است.

اما:

 
protected $color;
 

و:

 
private $weight;
 

از خارج کلاس قابل دسترسی مستقیم نیستند.


تفاوت Public، Protected و Private

برای اینکه تفاوت این سه سطح دسترسی را بهتر درک کنیم، می‌توان آنها را به صورت زیر خلاصه کرد:

سطح دسترسیداخل کلاسکلاس فرزندخارج کلاس
public✅✅✅
protected✅✅❌
private✅❌❌

این جدول یکی از مهم‌ترین نکات مربوط به Access Modifierها در PHP است.


چرا از Access Modifier استفاده می‌کنیم؟

استفاده از سطوح دسترسی فقط برای محدود کردن دسترسی نیست؛ بلکه یکی از پایه‌های مهم طراحی صحیح کلاس‌ها و مفهوم Encapsulation یا کپسوله‌سازی محسوب می‌شود.

فرض کنید یک کلاس بانکی داریم:

 
class BankAccount
{
    public $balance;
}
 

در این حالت هر قسمت از برنامه می‌تواند مستقیماً مقدار موجودی را تغییر دهد:

 
$account->balance = -500000;
 

این موضوع می‌تواند باعث ایجاد وضعیت نامعتبر در برنامه شود.

به همین دلیل می‌توانیم اطلاعات حساس را محدود کنیم و تغییر آنها را از طریق Methodهای مشخص انجام دهیم.

برای مثال:

 
<?php

class BankAccount
{
    private $balance = 0;

    public function deposit($amount)
    {
        if ($amount > 0) {
            $this->balance += $amount;
        }
    }

    public function get_balance()
    {
        return $this->balance;
    }
}

$account = new BankAccount();

$account->deposit(1000);

echo $account->get_balance();

?>
 

در این مثال مقدار balance به صورت private تعریف شده و از خارج کلاس نمی‌توانیم مستقیماً آن را تغییر دهیم.

این ساختار باعث می‌شود کنترل بیشتری روی اطلاعات داخل Object داشته باشیم.


Inheritance یا وراثت در PHP

یکی دیگر از مفاهیم بسیار مهم در برنامه‌نویسی شی‌گرا، Inheritance یا وراثت است.

وراثت به ما اجازه می‌دهد یک کلاس جدید را بر اساس یک کلاس موجود ایجاد کنیم و برخی Properties و Methods کلاس اصلی را در کلاس جدید به ارث ببریم.

کلاسی که ویژگی‌ها و رفتارهای خود را در اختیار کلاس دیگری قرار می‌دهد، معمولاً Parent Class یا کلاس والد نامیده می‌شود.

کلاسی که از کلاس والد ارث‌بری می‌کند، Child Class یا کلاس فرزند نام دارد.


چرا از Inheritance استفاده می‌کنیم؟

فرض کنید در یک پروژه کلاسی به نام Person داریم:

 
class Person
{
    public $name;
    public $age;

    public function introduce()
    {
        echo "Hello";
    }
}
 

حالا می‌خواهیم دو کلاس به نام‌های Student و Teacher داشته باشیم.

هر دو مورد، یک شخص هستند و بنابراین می‌توانند ویژگی‌هایی مانند نام و سن داشته باشند.

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

 
class Student extends Person
{
    // ویژگی‌ها و رفتارهای مخصوص Student
}
 

در اینجا Student کلاس فرزند و Person کلاس والد است.


کلمه کلیدی extends در PHP

برای ایجاد رابطه وراثت در PHP از کلمه کلیدی extends استفاده می‌کنیم.

ساختار کلی:

 
class ChildClass extends ParentClass
{
    // code
}
 

برای مثال:

 
class Strawberry extends Fruit
{
}
 

یعنی کلاس Strawberry از کلاس Fruit ارث‌بری می‌کند.


مثال کامل Inheritance در PHP

مثال زیر یک نمونه کامل از وراثت در PHP است:

 
<?php

class Fruit
{
    public $name;
    public $color;

    public function __construct($name, $color)
    {
        $this->name = $name;
        $this->color = $color;
    }

    public function intro()
    {
        echo "The fruit is {$this->name} and the color is {$this->color}.";
    }
}

class Strawberry extends Fruit
{
    public function message()
    {
        echo "Am I a fruit or a berry?<br>";
    }
}

$strawberry = new Strawberry("Strawberry", "Red");

$strawberry->message();

$strawberry->intro();

?>
 

در این مثال:

 
class Fruit
 

کلاس والد است.

و:

 
class Strawberry extends Fruit
 

کلاس فرزند محسوب می‌شود.

Object مربوط به Strawberry می‌تواند از Method خودش استفاده کند:

 
$strawberry->message();
 

و همچنین از Method به ارث رسیده از Fruit استفاده کند:

 
$strawberry->intro();
 

کدام اعضای کلاس به فرزند به ارث می‌رسند؟

در هنگام کار با Inheritance باید تفاوت Access Modifierها را به خوبی بدانیم.

اعضای public و protected می‌توانند در کلاس فرزند مورد استفاده قرار بگیرند، اما اعضای private مستقیماً در کلاس فرزند قابل دسترسی نیستند.

برای مثال:

 
class Fruit
{
    public $name;
    protected $color;
    private $weight;
}
 

کلاس فرزند می‌تواند به:

 
$name
 

و:

 
$color
 

دسترسی داشته باشد، اما نمی‌تواند مستقیماً به:

 
$weight
 

دسترسی پیدا کند.


استفاده از Propertyهای Protected در کلاس فرزند

برای مثال:

 
<?php

class Fruit
{
    protected $color = "Red";
}

class Strawberry extends Fruit
{
    public function show_color()
    {
        echo $this->color;
    }
}

$strawberry = new Strawberry();

$strawberry->show_color();

?>
 

در اینجا $color در کلاس والد protected است.

بنابراین کلاس Strawberry می‌تواند از طریق $this->color به آن دسترسی داشته باشد.

اما این دستور از خارج کلاس مجاز نیست:

 
$strawberry->color;
 

Overriding در PHP چیست؟

گاهی اوقات کلاس فرزند یک Method را از کلاس والد به ارث می‌برد، اما می‌خواهیم رفتار آن Method را متناسب با نیاز کلاس فرزند تغییر دهیم.

در این شرایط می‌توانیم Method والد را در کلاس فرزند Override یا بازنویسی کنیم.

به عبارت ساده، کلاس فرزند می‌تواند متدی با همان نام و امضای سازگار تعریف کند و رفتار مخصوص خودش را ارائه دهد.


مثال ساده از Method Overriding

فرض کنید کلاس والد متدی به نام intro() دارد:

 
<?php

class Fruit
{
    public function intro()
    {
        echo "I am a fruit.";
    }
}
 

حالا کلاس فرزند همین Method را بازنویسی می‌کند:

 
class Strawberry extends Fruit
{
    public function intro()
    {
        echo "I am a strawberry.";
    }
}
 

حالا اگر بنویسیم:

 
$strawberry = new Strawberry();

$strawberry->intro();
 

نسخه intro() که در کلاس Strawberry تعریف شده است اجرا می‌شود.

خروجی:

 
I am a strawberry.
 

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


مثال کامل‌تر از Overriding

 
<?php

class Animal
{
    public function sound()
    {
        echo "Animal makes a sound.";
    }
}

class Dog extends Animal
{
    public function sound()
    {
        echo "Dog barks.";
    }
}

class Cat extends Animal
{
    public function sound()
    {
        echo "Cat meows.";
    }
}

$dog = new Dog();
$cat = new Cat();

$dog->sound();

echo "<br>";

$cat->sound();

?>
 

در این مثال، هر دو کلاس Dog و Cat از Animal ارث‌بری کرده‌اند، اما هر کدام رفتار مخصوص خودشان را برای sound() تعریف کرده‌اند.


استفاده از parent در کلاس فرزند

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

در این شرایط می‌توانیم از کلمه کلیدی parent استفاده کنیم.

برای مثال:

 
<?php

class Fruit
{
    public function intro()
    {
        echo "I am a fruit.<br>";
    }
}

class Strawberry extends Fruit
{
    public function intro()
    {
        parent::intro();

        echo "I am a strawberry.";
    }
}

$strawberry = new Strawberry();

$strawberry->intro();

?>
 

در اینجا:

 
parent::intro();
 

نسخه Method موجود در کلاس والد را اجرا می‌کند.

سپس کد مخصوص کلاس Strawberry اجرا می‌شود.


Constructor و Inheritance

وراثت با Constructorها نیز ارتباط دارد.

فرض کنید کلاس والد Constructor داشته باشد:

 
<?php

class Fruit
{
    public $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}

class Strawberry extends Fruit
{
}

$strawberry = new Strawberry("Strawberry");

echo $strawberry->name;

?>
 

اگر کلاس فرزند Constructor خودش را تعریف نکرده باشد، در شرایط مربوط به وراثت می‌تواند از Constructor والد استفاده کند.

اما اگر کلاس فرزند Constructor خودش را داشته باشد، می‌توان در صورت نیاز Constructor والد را با parent::__construct() فراخوانی کرد.

برای مثال:

 
<?php

class Fruit
{
    public $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}

class Strawberry extends Fruit
{
    public $color;

    public function __construct($name, $color)
    {
        parent::__construct($name);

        $this->color = $color;
    }
}

$strawberry = new Strawberry("Strawberry", "Red");

echo $strawberry->name;
echo "<br>";
echo $strawberry->color;

?>
 

در اینجا:

 
parent::__construct($name);
 

باعث می‌شود Constructor کلاس والد نیز اجرا شود.


The final Keyword در PHP چیست؟

کلمه کلیدی final یکی دیگر از قابلیت‌های مهم در برنامه‌نویسی شی‌گرا PHP است.

final زمانی استفاده می‌شود که بخواهیم از Override شدن یک Method یا ارث‌بری از یک Class جلوگیری کنیم.

نکته بسیار مهم:

یک final class همچنان قابل نمونه‌سازی است؛ final بودن کلاس به این معنی نیست که نمی‌توان از آن Object ساخت. بلکه به این معنی است که کلاس دیگری نمی‌تواند از آن extends کند.


Final Class در PHP

اگر قبل از تعریف Class از final استفاده کنیم:

 
final class Fruit
{
    public function intro()
    {
        echo "This is a fruit.";
    }
}
 

کلاس دیگری نمی‌تواند از آن ارث‌بری کند:

 
class Apple extends Fruit
{
}
 

این کد با خطا مواجه خواهد شد.

بنابراین final class برای زمانی کاربرد دارد که می‌خواهیم جلوی ایجاد کلاس‌های فرزند برای یک کلاس مشخص را بگیریم.


آیا از Final Class می‌توان Object ساخت؟

بله.

این موضوع اهمیت زیادی دارد.

اگر کلاس به صورت final تعریف شده باشد:

 
final class Fruit
{
}
 

هنوز می‌توان از آن Object ایجاد کرد:

 
$fruit = new Fruit();
 

محدودیت final class مربوط به Inheritance است، نه ساخت Object.


Final Method در PHP

کلمه final فقط برای Class استفاده نمی‌شود و می‌توان آن را برای Method نیز به کار برد.

برای مثال:

 
<?php

class Fruit
{
    final public function intro()
    {
        echo "I am a fruit.";
    }
}

?>
 

در این حالت کلاس فرزند می‌تواند از Fruit ارث‌بری کند، اما نمی‌تواند Method intro() را Override کند.

مثلاً:

 
class Apple extends Fruit
{
    public function intro()
    {
        echo "I am an apple.";
    }
}
 

این کد با خطا مواجه می‌شود، زیرا intro() در کلاس والد به صورت final تعریف شده است.


تفاوت Final Class و Final Method

تفاوت این دو را می‌توان به شکل ساده این‌گونه بیان کرد:

Final Class

 
final class Fruit
{
}
 

یعنی:

هیچ کلاس دیگری نمی‌تواند از Fruit ارث‌بری کند.

Final Method

 
final public function intro()
{
}
 

یعنی:

کلاس‌های فرزند می‌توانند از کلاس ارث‌بری کنند، اما نمی‌توانند این Method را Override کنند.


چه زمانی از Final استفاده کنیم؟

استفاده از final زمانی مفید است که بخشی از منطق برنامه نباید توسط کلاس‌های فرزند تغییر داده شود.

برای مثال:

 
class Payment
{
    final public function validate()
    {
        // validation logic
    }
}
 

در این حالت می‌توان اجازه داد کلاس‌های مختلف از Payment ارث‌بری کنند، اما نمی‌خواهیم منطق validate() تغییر کند.

یا اگر کل کلاس نباید به عنوان Parent Class استفاده شود:

 
final class Configuration
{
    // configuration logic
}
 

در این حالت هیچ کلاس دیگری نمی‌تواند از Configuration ارث‌بری کند.


مقایسه Access Modifiers و Final

Access Modifier و final هر دو برای کنترل نحوه استفاده از کلاس‌ها و اعضای آنها کاربرد دارند، اما وظیفه متفاوتی دارند.

قابلیتکاربرد
publicدسترسی عمومی به Property یا Method
protectedدسترسی کلاس و کلاس‌های فرزند
privateدسترسی فقط در همان کلاس
final classجلوگیری از ارث‌بری از یک کلاس
final methodجلوگیری از Override شدن یک Method

بنابراین نباید private و final را یک مفهوم در نظر گرفت.

private درباره دسترسی صحبت می‌کند، در حالی که final درباره ارث‌بری و بازنویسی محدودیت ایجاد می‌کند.


یک مثال جامع از Access Modifiers و Inheritance

برای جمع‌بندی چند مفهوم می‌توانیم مثال زیر را بررسی کنیم:

 
<?php

class Person
{
    public $name;

    protected $age;

    private $nationalCode;

    public function __construct($name, $age, $nationalCode)
    {
        $this->name = $name;
        $this->age = $age;
        $this->nationalCode = $nationalCode;
    }

    public function show_info()
    {
        echo "Name: " . $this->name . "<br>";
        echo "Age: " . $this->age . "<br>";
        echo "National Code: " . $this->nationalCode . "<br>";
    }
}

class Student extends Person
{
    public function show_age()
    {
        echo "Age: " . $this->age;
    }
}

$student = new Student("Ali", 22, "1234567890");

echo $student->name;

echo "<br>";

$student->show_age();

echo "<br>";

$student->show_info();

?>
 

در این مثال:

  • $name به صورت public تعریف شده است.
  • $age به صورت protected تعریف شده است.
  • $nationalCode به صورت private تعریف شده است.
  • کلاس Student از Person ارث‌بری کرده است.
  • کلاس Student می‌تواند به $age دسترسی داشته باشد.
  • $nationalCode مستقیماً در کلاس Student قابل دسترسی نیست.
  • از خارج کلاس نیز فقط Propertyهای public قابل دسترسی مستقیم هستند.

نکات مهم Access Modifiers در PHP

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

استفاده از Public

زمانی که واقعاً نیاز است یک Property یا Method از بیرون کلاس قابل دسترسی باشد، می‌توان از public استفاده کرد.

استفاده از Protected

اگر اطلاعات یا رفتار باید در اختیار کلاس و کلاس‌های فرزند باشد اما از بیرون کلاس مستقیماً قابل دسترسی نباشد، protected گزینه مناسبی است.

استفاده از Private

برای اطلاعاتی که باید فقط توسط همان کلاس مدیریت شوند، private کاربرد دارد.

استفاده از Method به جای دسترسی مستقیم

در پروژه‌های حرفه‌ای، گاهی بهتر است اطلاعات داخلی کلاس مستقیماً در اختیار بخش‌های مختلف برنامه قرار نگیرد و از Methodهای مشخص برای دریافت یا تغییر آنها استفاده شود.

این روش کنترل بیشتری روی منطق برنامه ایجاد می‌کند.


نکات مهم Inheritance در PHP

وراثت یکی از ابزارهای مهم OOP است، اما نباید بدون دلیل از آن استفاده کرد.

قبل از ایجاد رابطه Parent و Child بهتر است بررسی کنیم آیا واقعاً رابطه منطقی بین دو کلاس وجود دارد یا خیر.

برای مثال:

 
Animal
 ├── Dog
 ├── Cat
 └── Bird
 

یک رابطه منطقی از نوع «یک حیوان است» را نشان می‌دهد.

همچنین:

 
Person
 ├── Student
 └── Teacher
 

نمونه دیگری از رابطه Parent و Child است.

در مقابل، هر دو کلاس بودن در یک پروژه لزوماً به این معنی نیست که یکی باید از دیگری ارث‌بری کند.


جمع‌بندی

در این بخش با چند مفهوم بسیار مهم در برنامه‌نویسی شی‌گرا PHP آشنا شدیم.

ابتدا Access Modifiers را بررسی کردیم. PHP سه سطح دسترسی اصلی دارد:

 
public
protected
private
 

public امکان دسترسی از داخل و خارج کلاس را فراهم می‌کند، protected دسترسی را به کلاس و کلاس‌های فرزند محدود می‌کند و private فقط از داخل همان کلاسی که عضو در آن تعریف شده قابل دسترسی است.

سپس با Inheritance یا وراثت آشنا شدیم. با استفاده از کلمه کلیدی extends می‌توان یک کلاس فرزند ایجاد کرد که از قابلیت‌های کلاس والد استفاده کند:

 
class Strawberry extends Fruit
{
}
 

کلاس فرزند می‌تواند قابلیت‌های جدیدی به ساختار خود اضافه کند و در شرایط مناسب، Methodهای به ارث رسیده را نیز Override کند.

همچنین یاد گرفتیم که با استفاده از:

 
parent::
 

می‌توان به اعضای مناسب کلاس والد دسترسی پیدا کرد؛ برای مثال:

 
parent::__construct();
 

برای فراخوانی Constructor والد کاربرد دارد.

در نهایت با final آشنا شدیم. اگر یک کلاس به صورت final تعریف شود، کلاس دیگری نمی‌تواند از آن ارث‌بری کند:

 
final class Fruit
{
}
 

اما همچنان می‌توان از این کلاس Object ساخت.

همچنین اگر یک Method به صورت final تعریف شود، کلاس‌های فرزند نمی‌توانند آن Method را Override کنند.

این مفاهیم پایه‌ای، بخش مهمی از برنامه‌نویسی شی‌گرا در PHP را تشکیل می‌دهند و درک صحیح آنها برای یادگیری مباحث پیشرفته‌تر مانند Encapsulation، Polymorphism، Abstract Classes، Interfaces، Traits و طراحی ساختار پروژه‌های حرفه‌ای PHP ضروری است.

اشتراک گذاری :
مریم گوهرزاد
نویسنده

مریم گوهرزاد

مدرس و بنیانگذار هلدینگ آرتا رسانه. برنامه نویس و محقق حوزه بلاکچین و توسعه‌دهنده بلاکچین | متخصص Solidity | توسعه‌دهنده وب Full-Stackمن یک توسعه‌دهنده علاقه‌مند به فناوری‌های بلاکچین و وب ۳ هستم و در زمینه Solidity، توسعه قراردادهای هوشمند و ساخت برنامه‌های غیرمتمرکز (DApps) فعالیت می‌کنم. تمرکز من بر طراحی و پیاده‌سازی راهکارهایی است که در کنار بهره‌گیری از فناوری‌های نوین، عملکرد مناسب، امنیت و تجربه کاربری مطلوبی ارائه دهند.در کنار تخصص در حوزه بلاکچین، به عنوان یک توسعه‌دهنده وب Full-Stack نیز در طراحی و توسعه وب‌سایت‌ها و برنامه‌های تحت وب فعالیت می‌کنم. تجربه کار در بخش‌های Front-End و Back-End به من این امکان را داده است که پروژه‌ها را از مرحله ایده و طراحی تا توسعه و اجرا، با دیدی جامع دنبال کنم. در فرآیند توسعه، توجه ویژه‌ای به کدنویسی تمیز، معماری مناسب، طراحی واکنش‌گرا، عملکرد مطلوب و تجربه کاربری روان دارم.

TEST_VALUE_123
https://t.me/artarasaneh
tel:09193426251
https://wa.me/+989193426251
https://instagram.com/artarasaneh_com