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


369

परिदृश्य:

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);
    }
}

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

वहाँ यह काम करने के लिए एक रास्ता है या मैं पूरी तरह से इस समारोह की तुलना में अधिक जटिल है, जो विशेषता समारोह को ओवरराइड करना चाहिए :)

जवाबों:


640

आपका अंतिम समय लगभग था:

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

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

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

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


20
बस स्पष्ट करने के लिए - एक बार जब आपकी कक्षा एक ही विधि को परिभाषित करती है, तो यह स्वचालित रूप से विशेषता को पार कर जाती है। खाली होने पर यह विशेषता विधि के रूप में @ircmaxell भरती है।
येहसेफ

2
@PhillipWhelan अच्छा होगा यदि आप "अपेक्षा के अनुरूप काम नहीं करते" पर अधिक जानकारी जोड़ सकते हैं। इस तरह लिखा गया है कि यह समझने में बहुत मदद नहीं करता है कि किस तरह के गलत व्यवहार की उम्मीद है, और हमें विश्वास नहीं दिलाता है कि यह आपके लिए अस्थायी गलती नहीं है। हो सकता है कि जिस मुद्दे के बारे में आप बात कर रहे हैं, उसके बारे में कुछ SO प्रश्न हो? (आखिरकार) धन्यवाद।
कामाफेदर

1
समस्या यह है कि विशेषता में अन्य सभी विधियाँ शामिल नहीं हैं।
मल्हल

2
अपने विशेषता समारोह स्थिर हो जाएगा, तो आप से बुला समारोह यहां पहुंच सकता है: बस में संदर्भ के लिएA::calc(1)
velop

4
जैसा कि फिलिप ने उल्लेख किया है (मुझे लगता है), आप एक विशेषता के एक तरीके के लिए यह कैसे करेंगे जबकि एक ही विशेषता के सभी अन्य तरीकों को सामान्य रूप से शामिल करेंगे? स्पष्ट रूप से प्रत्येक विधि को स्पष्ट रूप से संदर्भित किए बिना।
गनेट

14

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

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 पर देख सकते हैं


8

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

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);
    }
}

6
यह दृष्टिकोण traitएस के उपयोग से आपको होने वाले किसी भी लाभ को दाढ़ी देगा । जैसे कई वर्गों में कई लक्षणों का संयोजन करना (जैसे एक वर्ग में ए, बी, दूसरे वर्ग में विशेषता बी, सी, डी, दूसरे वर्ग में विशेषता ए, सी और इतने पर)
Ionua Staicu

3
नहीं, इस दृष्टिकोण का उपयोग करने के बाद भी आपके पास एक विशेषता होने के फायदे हैं। आप इस विशेषता का उपयोग IntClass में कर सकते हैं, लेकिन आप चाहें तो इसे कई अन्य वर्गों में भी उपयोग कर सकते हैं। ट्रेट बेकार हो जाएगा, अगर इसका उपयोग केवल इंटक्लास में किया गया था। उस स्थिति में, उस कक्षा में सीधे कैल्क () पद्धति रखना बेहतर होगा।
मार्सिनी

यह पूरी तरह से मेरे लिए काम नहीं करेगा। ScreenablePerson::save()मौजूद है, विशेषता Candidateका उपयोग करता Validatingहै और विस्तार करता है ScreenablePerson, और तीनों वर्गों में है save()
थियोडोर आर। स्मिथ

1

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

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.