المسارات
/
PHP
PHP
/
المنهج
/
التباين والتباين العكسي
ال

التباين والتباين العكسي في PHP

{zero: "لا توجد تمارين", one: "1 تمرين", two: "تمرينان", few: "%{count} تمارين", many: "%{count} تمرينًا", other: "%{count} تمرين"}

نبذة عن التباين والتباين العكسي

التغاير المشترك والتغاير المضاد

عند استخدام أنواع الاتحاد، يجب أن تكون على دراية بمفهومَي التغاير المشترك والتغاير المضاد. هذان المفهومان مشروحان في التوثيق، لكن هذه الأمثلة قد تساعدك.

لنفترض أن لدينا صنف Calculator يستخدم دالة مثل المثال السابق:

class Calculator
{
    public function add(int|float $x, int|float $y): int|float
    {
        return $x + $y;
    }
}

إذا ورثت من الصنف، فيُسمح لك بتغيير أنواع المعاملات وأنواع الإرجاع، لكن وفق القواعد التالية فقط.

أولًا، يمكن أن تكون أنواع المعاملات "أوسع"، أي أنها تقبل أنواعًا أكثر من الصنف الأساسي. على سبيل المثال، هذا مسموح:

class StringCalc extends Foo
{
    public function add(float|int|string $x, float|int|string $y): int|float
    {
        if (!is_numeric($x) || !is_numeric($y)) {
            throw new \InvalidArgumentException('$x and $y must be numeric');
        }
        return $x + $y;
    }
}

يمكننا استبدال Calculator الأصلي بـ StringCalc وسيظل كل شيء يعمل. سيظل بإمكان المستدعي تمرير قيم من النوع float أو int كما كان في الأصل، وسيظل نوع الإرجاع هو int أو float المتوقع.

وبالمثل، يمكنك تضييق نوع الإرجاع، أي جعله أكثر تحديدًا بإزالة أنواع من نوع الاتحاد. هذا المثال يستفيد من هذه القاعدة:

class IntCalc extends Calculator
{
    public function add(float|int $x, float|int $y) : int
    {
        return (int)($x + $y);
    }
}

بما أن IntCalc لا يزال يقبل int وfloat، فيمكنه أن يحل محل Calculator الأصلي بلا مشاكل.

لقراءة المزيد عمّا هو مسموح وما هو غير مسموح، يمكنك الرجوع إلى مبدأ استبدال ليسكوف (LSP).

ولمثال على ما لن يكون مسموحًا، ألقِ نظرة على InvalidCalc أدناه:

class InvalidCalc extends Calculator
{
    public function add(int $x, int $y) : int|float|string
    {
        // Declaration must be compatible with Calculator->add(x: float|int, y: float|int)

        // Return type declaration must be compatible with Calculator->add(x: float|int, y: float|int) : float|int
    }
}

لن يُصرَّف صنف InvalidCalc وسيواجه مشكلتين. فبتقليله لما هو مسموح به كمعامل، لن يستطيع InvalidCalc أن يحل محل Calculator الأصلي لأنه لم يعد يقبل float. إضافة إلى ذلك، يمكنه الآن أن يُرجع string، وهو أيضًا ليس ضمن أنواع الإرجاع المسموح بها في الصنف الأصلي.

تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة