php - विशेषता समारोह को ओवरराइड करने के लिए कैसे करें और इसे ओवरराइड फ़ंक्शन से कॉल करें?


परिदृश्य:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A;

    function calc($v) {
        $v++;
        return A::calc($v);
    }
}

print (new MyClass())->calc(2); // should print 4

यह कोड काम नहीं करता है, और मुझे ऐसे गुण समारोह को कॉल करने का कोई तरीका नहीं मिल सकता है जैसे कि यह विरासत में मिला था। मुझे self::calc($v) , static::calc($v) , parent::calc($v) , A::calc($v) और निम्नलिखित कॉल करने की कोशिश की गई:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A {
        calc as traitcalc;
    }

    function calc($v) {
        $v++;
        return traitcalc($v);
    }
}

कुछ भी काम नहीं करता है।

क्या यह काम करने का एक तरीका है या मुझे पूरी तरह से गुण समारोह को ओवरराइड करना चाहिए जो कि इस से अधिक जटिल है :)


Answers


आपका अंतिम एक लगभग वहां था:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A {
        calc as protected traitcalc;
    }

    function calc($v) {
        $v++;
        return $this->traitcalc($v);
    }
}

गुण एक वर्ग नहीं है। आप सीधे अपने सदस्यों तक पहुंच नहीं सकते हैं यह मूल रूप से बस स्वचालित कॉपी और पेस्ट है ...




यदि क्लास सीधे विधि का कार्यान्वयन करता है, तो यह गुण संस्करण का उपयोग नहीं करेगा। शायद आप के बारे में क्या सोच रहे हैं:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    function calc($v) {
        return $v+2;
    }
}

class MyChildClass extends MyClass{
}

class MyTraitChildClass extends MyClass{
    use A;
}

print (new MyChildClass())->calc(2); // will print 4

print (new MyTraitChildClass())->calc(2); // will print 3

चूंकि बाल कक्षाएं विधि को प्रत्यक्ष रूप से लागू नहीं करती हैं, वे पहले उस विशेषता का उपयोग करेंगे, यदि वहां अन्यथा माता-पिता वर्ग का उपयोग किया जाए।

यदि आप चाहते हैं, तो गुण पैतृक वर्ग में विधि का उपयोग कर सकते हैं (यह सोचते हुए कि विधि वहां होगी) उदा

trait A {
    function calc($v) {
        return parent::calc($v*3);
    }
}
// .... other code from above
print (new MyTraitChildClass())->calc(2); // will print 8 (2*3 + 2)

आप ओवरराइड करने के तरीकों के लिए भी प्रदान कर सकते हैं, लेकिन फिर भी निम्न प्रकार की विशेषता का उपयोग करें:

trait A {
    function trait_calc($v) {
        return $v*3;
    }
}

class MyClass {
    function calc($v) {
        return $v+2;
    }
}


class MyTraitChildClass extends MyClass{
    use A {
      A::trait_calc as calc;
    }
}


class MySecondTraitChildClass extends MyClass{
    use A {
      A::trait_calc as calc;
    }

    public function calc($v) {
      return $this->trait_calc($v)+.5;
    }
}


print (new MyTraitChildClass())->calc(2); // will print 6
echo "\n";
print (new MySecondTraitChildClass())->calc(2); // will print 6.5

आप इसे http://sandbox.onlinephpfunctions.com/code/e53f6e8f9834aea5e038aec4766ac7e1c19cc2b5 पर देख सकते हैं




एक वैकल्पिक दृष्टिकोण यदि दिलचस्पी है - एक अतिरिक्त मध्यवर्ती कक्षा के साथ सामान्य ओओओ का उपयोग करना। यह पेरेंट :: विधि नाम के साथ उपयोग को सरल करता है

trait A {
    function calc($v) {
        return $v+1;
    }
}

// an intermediate class that just uses the trait
class IntClass {
    use A;
}

// an extended class from IntClass
class MyClass extends IntClass {
    function calc($v) {
        $v++;
        return parent::calc($v);
    }
}



एक और विशेषता का प्रयोग करना:

trait ATrait {
    function calc($v) {
        return $v+1;
    }
}

class A {
    use ATrait;
}

trait BTrait {
    function calc($v) {
        $v++;
        return parent::calc($v);
    }
}

class B extends A {
    use BTrait;
}

print (new B())->calc(2); // should print 4