2014-05-08 6 views
5

अगर मैं इस तरह के रूप में एक एस 4 वर्ग है:क्लास फ़ंक्शन का उपयोग करते हुए एस 4 ऑब्जेक्ट की "कक्षा" को बदलते समय क्या हो रहा है?

setClass("MyClass", 
    representation(
     data="data.frame", 
     name="character")) 

और यह दृष्टांत (obj को कहते हैं),

obj <- new('MyClass', data=data.frame(1:3), name='An S4 class') 

मैं निम्नलिखित प्रतिनिधित्व करना होगा: अब तक

An object of class "MyClass" 
Slot "data": 
    X1.3 
1 1 
2 2 
3 3 

Slot "name": 
[1] "An S4 class" 

बहुत अच्छा।

हालांकि, अगर मैं का उपयोग कर "वर्ग" को बदलने की कोशिश:

class(obj) <- "animal" 

मैं अब

An object of class "animal" 
<S4 Type Object> 
attr(,"data") 
    X1.3 
1 1 
2 2 
3 3 
attr(,"name") 
[1] "An S4 class" 

मिलता और अगर मैं क्या यह अभी भी एक एस 4 वर्ग है की जाँच करने के लिए प्रयास करें, यह वापस लौटें:

>isS4(obj) 
[1] TRUE 

वास्तव में क्या हो रहा है? "स्लॉट" गुणों में क्यों बदल गए? क्या यह वास्तव में अभी भी एक एस 4 वर्ग है?

अद्यतन:

व्यापक जवाब के लिए धन्यवाद। बस स्पष्ट करने के लिए, मैं इसे किसी भी वास्तविक परिदृश्य में काम करने या उपयोग करने की उम्मीद नहीं कर रहा था। मैं बस इस व्यवहार के पीछे तंत्र को बेहतर समझना चाहता था। इसके अलावा, "सर्वश्रेष्ठ" उत्तर चुनना मुश्किल है (वे सभी उत्कृष्ट हैं) लेकिन, एसओ की भावना के भीतर, मुझे एक चुनना होगा।

+1

मुझे लगता है कि आपने अभी क्लास एट्रिब्यूट जोड़ा है, और हाइब्रिड एस 3-एस 4 ऑब्जेक्ट बनाया है। मैं किसी भी मुद्रण विधियों पर भरोसा नहीं करता क्योंकि उन्हें शायद इस तरह की अजीब वस्तु से निपटने के लिए डिजाइन नहीं किया गया था। – hadley

उत्तर

3

एस 4 गुणों के रूप में स्लॉट लागू करता है। यह आमतौर पर उपयोगकर्ता से छिपा हुआ है, लेकिन आसानी से

> attributes(setClass("MyClass", representation(x="integer"))()) 
$x 
integer(0) 

$class 
[1] "MyClass" 
attr(,"package") 
[1] ".GlobalEnv" 

थोड़ा और रक्तमय विस्तार में देखा जाता है, हमारे पास

> .Internal(inspect(setClass("MyClass", representation(x="integer"))())) 
@1fe4dfd8 25 S4SXP g0c0 [OBJ,NAM(2),S4,gp=0x10,ATT] 
ATTRIB: 
    @1fe4dfa0 02 LISTSXP g0c0 [] 
    TAG: @23c8978 01 SYMSXP g0c0 [MARK,NAM(2)] "x" 
    @1fe4df68 13 INTSXP g0c0 [] (len=0, tl=0) 
    TAG: @2363208 01 SYMSXP g0c0 [MARK,NAM(2),LCK,gp=0x4000] "class" (has value) 
    @1fd9f1b8 16 STRSXP g0c1 [NAM(2),ATT] (len=1, tl=0) 
     @2e09e138 09 CHARSXP g0c1 [gp=0x61] [ASCII] [cached] "MyClass" 
    ATTRIB: 
     @1fd9fb20 02 LISTSXP g0c0 [] 
    TAG: @236cc00 01 SYMSXP g0c0 [MARK,NAM(2)] "package" 
    @1fd9f278 16 STRSXP g0c1 [NAM(2)] (len=1, tl=0) 
     @23cc938 09 CHARSXP g0c2 [MARK,gp=0x61] [ASCII] [cached] ".GlobalEnv" 

से पता चलता कौन सा कि अंतर्निहित एस अभिव्यक्ति सभी आर वस्तुओं का प्रतिनिधित्व करते थे है जुड़े गुणों की एक सूची के साथ एक एस 4 एसएक्सपी।

एस 3-आईएसएम class<- का उपयोग करके आपने बनाया है, जैसा कि @ हैडली पॉइंट आउट, हाइब्रिड राक्षस है। class<- केवल अंतर्निहित S4SXP को बदलने के बिना, क्लास विशेषता अद्यतन करता है। जब आप ऑब्जेक्ट प्रिंट करते हैं, तो यह "पशु" वर्ग, शायद print.default की वस्तुओं के लिए प्रिंट विधि का उपयोग करता है। दूसरी तरफ, आईएस 4 परीक्षण करता है कि एस-एक्सप्रेशन एस 4 एसएक्सपी है, जो यह है। तो आपको प्रत्येक में से कुछ मिल गया है ...

कॉन्स, शायद setAs फ़ंक्शन , using (ओबीजे, "पशु") के रूप में रिलीज को लागू करके।

2

यह पूछना थोड़ा मुश्किल है कि एस 4 ऑब्जेक्ट क्या है। यदि हम R internals से परिभाषा लेते हैं, हां, यह अभी भी एक S4 ऑब्जेक्ट है क्योंकि S4 bit अभी भी सेट है।

obj <- new('MyClass', data=data.frame(1:3), name='An S4 class') 
attr(obj, 'class') 
## [1] "MyClass" 
## attr(,"package") 
## [1] ".GlobalEnv" 

obj2 <- obj 
class(obj2) <- 'animal' 
attr(obj, 'class') 
## [1] "MyClass" 

ध्यान दें कि फर्क सिर्फ इतना है (जहाँ तक स्मृति प्रतिनिधित्व का सवाल है) obj और obj2 के बीच class विशेषता के साथ जुड़े package विशेषता की कमी वास्तव में है। हम फोन करके इस "ठीक" कर सकते हैं:

attr(class(obj2), "package") <- ".GlobalEnv" 

लेकिन इस तरह के एक मामले में हम भी एक ही "अजीब" परिणाम प्राप्त:

print(obj2) 
## An object of class "animal" 
## <S4 Type Object> 
## attr(,"data") 
## X1.3 
## 1 1 
## 2 2 
## 3 3 
## attr(,"name") 
## [1] "An S4 class" 

तो चलो विधि मुद्रण obj और obj2 के लिए जिम्मेदार के लिए देखो । दोनों मामलों में यह हस्ताक्षर ANY के साथ show के माध्यम से किया जाता है। प्रिंटिंग getMethod("show", "ANY") हमें showDefault फ़ंक्शन पर भेजता है।

और पहली बात यह है कि showDefault करता है:

... 
clDef <- getClass(cl <- class(object), .Force = TRUE) 
... 

तुम देखो, getClass GlobalEnv में animal के लिए औपचारिक वर्ग परिभाषा नहीं मिल रहा। यही कारण है कि यह show(unclass(object)) पर कॉल करता है और हम सबकुछ विशेषता के रूप में देखते हैं (सीएफ print(unclass(obj))) (EDIT: विशेषताएँ: मार्टिन मॉर्गन के उत्तर में क्यों समझाया गया है)।

2

obj वर्ग विशेषता 'जानवर' को जोड़ने के बाद एक एस 4 वस्तु के रूप में व्यवहार करने के लिए जारी रहेगा, लेकिन ध्यान दें कि यह संकर वस्तु में एक स्लॉट के मान को परिवर्तित असफल हो जायेगी जब तक animal ही के एक स्लॉट के साथ एक परिभाषित एस 4 वर्ग है नाम। इसके अतिरिक्त, स्लॉट वैल्यू बदलने का कार्य किसी भी स्लॉट को भी छोड़ देगा जो animal में नहीं है।

# define animal with the same slots 
setClass("animal", representation(data="data.frame", name="character")) 
# register conversion function 
setAs("MyClass", "animal", function(from, to)new(to, [email protected], [email protected])) 
# new obj 
obj <- new('MyClass', data=data.frame(1:3), name='An S4 class') 
as(obj, 'animal') 
:

[email protected] <- data.frame() # FAILS, animal not defined 
setClass("animal", representation(data="data.frame")) 
[email protected] <- data.frame() # works, but drops name 

@MartinMorgan बताते हैं के रूप में, एक से दूसरे एस 4 वर्ग बदलने के लिए सही तरीका setAs के साथ एक रूपांतरण समारोह रजिस्टर और फिर नया वर्ग के नाम के साथ वस्तु पर as कॉल करने के लिए है

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

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