2012-08-13 12 views
249

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

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

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

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

उत्तर

431

आपका पिछले एक लगभग वहाँ था ओवरराइड करना होगा:

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

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

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

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

+2

बिल्कुल सही! धन्यवाद! जाहिर है कि मेरा दिमाग बेकार पिघल गया था। :) – Shu

+8

सिर्फ स्पष्टीकरण के लिए - एक बार आपकी कक्षा एक ही विधि को परिभाषित करती है, तो यह स्वचालित रूप से विशेषता को ओवरराइड करता है। इस विधि में विशेषता भर जाती है क्योंकि @ रिककैक्सेल खाली होता है जब यह खाली होता है। – Yehosef

+0

अभी तक अज्ञात कारणों से इसने पूरी तरह से एक विशेषता को खराब कर दिया है, मैंने इसे लागू किया है। जब आप यह कर रहे हैं तो अन्य तरीकों की विशेषता के रूप में अपेक्षित काम नहीं कर सकते हैं। –

7

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

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

4

एक वैकल्पिक दृष्टिकोण पर काम करता है, तो रुचि देख सकते हैं - साथ सामान्य ओओयू तरीके का उपयोग करने के लिए एक अतिरिक्त मध्यवर्ती वर्ग। यह माता पिता के साथ उपयोग को सरल :: 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); 
    } 
} 
+5

यह दृष्टिकोण 'विशेषता' का उपयोग करके आपके पास कोई लाभ देगा। कई वर्गों में कई लक्षणों को संयोजित करने की तरह (उदाहरण के लिए एक कक्षा में विशेषता ए, बी, किसी अन्य वर्ग में बी, सी, डी विशेषता, किसी अन्य वर्ग में ए, सी का पता लगाएं) और इस तरह से, –

+3

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

0

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

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 
संबंधित मुद्दे