2012-08-24 17 views
7

this प्रश्न से संबंधित है, लेकिन थोड़ा अलग और उम्मीद है कि अधिक स्पष्ट है।औपचारिक विधि परिभाषाओं का उपयोग करते हुए एस 3 वस्तुओं के लिए एस 3 शैली प्रेषण

मैं स्वच्छ को औपचारिक रूप से एस 4 और एस 3 कक्षाओं के लिए विधियों को पंजीकृत करने के तरीके की तलाश में हूं, लेकिन प्रेषण के लिए भयानक एस 3-डॉट-नामकरण-योजना पर भरोसा किए बिना। एक उदाहरण:

setClass("foo"); 
setClass("bar"); 

setGeneric("test", function(x, ...){ 
    standardGeneric("test"); 
}); 

setMethod("test", "bar", function(x, ...){ 
    return("success (bar)."); 
}); 

obj1 <- 123; 
class(obj1) <- "bar"; 
test(obj1); 

यह उदाहरण दिखाता है कि कैसे हम वर्ग bar की S3 वस्तुओं के लिए एक test विधि रजिस्टर कर सकते हैं, समारोह test.bar है, जो बहुत अच्छा है नाम के लिए आवश्यकता के बिना। हालांकि, सीमा यह है कि अगर हम इस तरह से विधियों को पंजीकृत करते हैं, तो उन्हें केवल वस्तु के पहले एस 3 वर्ग में भेजा जाएगा। उदा:

obj2 <- 123; 
class(obj2) <- c("foo", "bar"); 
test(obj2); 

यह काम नहीं करता है, क्योंकि एस 4 विधि भेजने केवल वर्ग foo और उसके सुपर-क्लास की कोशिश करेंगे। यह उदाहरण कैसे बढ़ाया जा सकता है ताकि foo के लिए कोई उचित विधि नहीं मिलने पर bar के लिए यह स्वचालित रूप से test विधि का चयन करेगा? जैसे एस 3 शैली प्रेषण लेकिन सब कुछ नामकरण करने के लिए वापस जाने के बिना test.foo और test.bar?

तो संक्षेप में: औपचारिक विधि प्रेषण का उपयोग करने वाला एक सामान्य फ़ंक्शन कैसे बनाएं, लेकिन इसके अलावा कई कक्षाओं के साथ S3 ऑब्जेक्ट्स के लिए किसी ऑब्जेक्ट की दूसरी, तीसरी, आदि कक्षा पर वापस आना।

उत्तर

2

आप एक विधि

test = function(x, ...) UseMethod("test") 

setGeneric("test") 

.redispatch = function(x, ...) 
{ 
    if (is.object(x) && !isS4(x) && length(class(x)) != 1L) { 
     class(x) = class(x)[-1] 
     callGeneric(x, ...) 
    } else callNextMethod(x, ...) 
} 

setMethod(test, "ANY", .redispatch) 

लिख सकता है लेकिन मैं व्यक्तिगत रूप से इस तरह से एस 3 और एस 4 मिश्रण नहीं होगा।

+0

हाँ मैं कुछ ऐसा कर रहा हूं; हालांकि तथ्य यह है कि आप वास्तव में एक्स के वर्ग गुण को बदल रहे हैं, अवांछित साइड इफेक्ट्स हो सकते हैं ... क्या कोई तरीका है कि आप ऑब्जेक्ट को संशोधित किए बिना अगली विधि में भेज सकते हैं? – Jeroen

+0

मेरे पास आपके लिए कोई जवाब नहीं है; मुझे लगता है कि एस 3 कक्षा 'बार' पर काम कर रहे 'बार' के लिए एस 4 विधि कार्यान्वयन का दुर्घटना है, और आप बहुत ही कमजोर नींव पर एक जटिल संरचना बना रहे हैं। –

3

?setOldClass जवाब दे देंगे:

setOldClass(c("foo", "bar")) 

setGeneric("test", function(x, ...)standardGeneric("test")) 
setMethod("test", "bar", function(x, ...)return("success (bar).")) 
+0

तो यह बिल्कुल * नहीं * मैं चाहता हूं। इसे कक्षाओं "फू" और "बार" के बीच औपचारिक विरासत की आवश्यकता होती है, जो मामला नहीं हो सकता है। मैं चाहता हूं कि यह x = कुछ के लिए वर्ग = [x, "bar"] के साथ किसी भी मनमानी वस्तु के लिए काम करे, बिना किसी संभावित वर्ग x के लिए x और "bar" के बीच विरासत घोषित किए। मान लीजिए कि किसी और ने कक्षाओं ["चिड़ियाघर", "बार"] के साथ एक वस्तु बनाई है, फिर 'test ") फ़ंक्शन" बार "के लिए विधि का चयन करने के लिए पर्याप्त स्मार्ट होना चाहिए। – Jeroen