2012-03-01 22 views
9

मैं कुछ कोड डीबग करने की कोशिश कर रहा था जो मिश्रणों का उपयोग करता है और मैं इस उदाहरण में अपनी समस्या को कम करने में सक्षम था। मेरे पास एक अभिभावक वर्ग है जो एक मिश्रण और एक बच्चे वर्ग के माध्यम से विधियों को प्राप्त करता है जो माता-पिता से विरासत में मिलता है। अगर मैं बच्चा वर्ग यह काम करता है का एक उदाहरण पर एक विधि को बदलने का प्रयास विधि है कि मैं कर रहा हूँ की जगह से पहले ही बदल दिया जाता है माता पिता वर्ग का एक उदाहरण पर बुलाया गया था नहीं कर देते। यह तो कहा गया है अगर मैं बदल नहीं सकते यहग्रोवी यहां क्या कर रहा है?

तो यह कोड:

class M { 
    protected foo() { println 'foo' } 
} 

@Mixin(M) class A { 
def bar() { foo() } 
} 

class B extends A {} 

def b = new B() 
def a = new A() 
a.bar() //<-- comment out this line and see the difference 
b.metaClass.foo = {println 'winning'} 
b.bar() 

निकलेगा:

foo

foo

लेकिन अगर आप लाइन 13 पर टिप्पणी करते हैं (टिप्पणी के साथ एक टिप्पणी जो इसे टिप्पणी करने के लिए कहता है) आपको मिलेगा:

ऐसा क्यों होता है जीत? मुझे उम्मीद है कि ग्रोवी के मेटाक्लास मॉडल के संदर्भ में यह कुछ समझ में आता है, लेकिन मुझे यह नहीं मिला।

यह ग्रूवी 1.8.6

+1

मैं ग्रोवी 1.8.4 में इसे पुन: पेश कर सकते हैं। मुझे एक बग की तरह बदबू आ रही है; लेकिन मैं ग्रोवी मेटा प्रोग्रामिंग में बहुत ज्यादा नहीं हूं, इसलिए मुझे नहीं पता। – epidemian

+0

नोट के लिए धन्यवाद, मुझे यह सुनिश्चित करना होगा कि अगर मैं उस पर एक बग दर्ज कर रहा हूं। – mfollett

+0

मैं इसे groovy उपयोगकर्ता मेलिंग सूची पर पूछूंगा, मुझे एक बग की तरह बदबू आ रही है ... –

उत्तर

3

metaClass एक विधि कॉल और mixins अपने स्वयं के हैंडलर है पर देखा जाता है है। दोनों आलसी लोड और स्थिर हैं, यदि आप कोई विधि नहीं कहते हैं तो स्थिर आलसी लोडिंग नहीं होती है।
मिक्सिन मेटा क्लास ओवरराइड पर प्राथमिकता लेते हैं, यही कारण है कि यह foo प्रदर्शित करता है और यदि आप ए
प्रारंभ करते हैं तो उस मेटा को परिभाषित किया जाता है, जिस पर इसे लागू किया जाता है, ताकि इसे कक्षा में हल किया जा सके ताकि आपको ऑब्जेक्ट.क्लास की आवश्यकता हो। .metaClass (यानी यहां बीमेटा क्लास)। दिलचस्प बात यह है इस पैदावार:

बी पर
groovy.lang.MissingMethodException: No signature of method: B.foo() is applicable for argument types:() values: [] 
Possible solutions: foo(), foo(java.lang.Object), bar(), any(), use([Ljava.lang.Object;), find(groovy.lang.Closure) 

परिभाषित foo त्रुटि को हल:

class B extends A { 
    def foo() { println 'not winning' } 
} 

आपका जवाब है कि Mixin के वर्ग metastore को प्रभावित करता है, और कक्षा तरीकों वस्तु metastore तरीकों से प्राथमिकता दी जाती है।

सबूत:

@Mixin(M) 
class B extends A { 

} 

a.bar() //<-- comment out this line and see the difference 
B.metaClass.foo = {println 'class winning'} 
b.metaClass.foo = {println 'object winning'} 
b.bar() 

पैदावार:

foo 
class winning 

एक अलग दृष्टिकोण

class M { 
    protected foo() { println 'foo' } 
} 

@Mixin(M) class A { 
def bar() { foo() } 
} 

class B extends A { 
    def bar() { foo() } 
} 

class C extends B { 
    def foo() { println 'wat' } 
} 

@Mixin(M) 
class D extends C { } 

def b = new B() 
def a = new A() 
def c = new C() 
def d = new D() 


a.bar() //<-- comment out this line and see the difference 
b.metaClass.foo = {println 'winning'} 
b.bar() 

c.metaClass.foo = {println 'losing'} 
c.bar() 

d.metaClass.foo = {println 'draw'} 
d.bar() 

पैदावार

foo 
winning 
wat 
wat 
+0

क्या आपके पास कोई स्रोत है जिसका आप इस जानकारी के लिए उद्धरण दे सकते हैं? मैं पूरी तरह से आपके उत्तर का पालन नहीं करता हूं और मुझे ग्रोवी के मेटास्टोर पर कोई जानकारी नहीं मिल रही है। – mfollett

+0

यह सब कंसोल के साथ प्रलेखन और झुकाव से लिया जाता है। आपका प्रश्न बहुत दिलचस्प है और मेरी राय में एक ब्लॉग पोस्ट के लिए पात्र है। दस्तावेज़ के डायनामिक ग्रोवी पेज पहले से ही कुछ उत्तर प्रदान करते हैं http://groovy.codehaus.org/Per-Instance+MetaClass – Gepsens

संबंधित मुद्दे