當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


R setClass 創建類定義


R語言 setClass 位於 methods 包(package)。

說明

創建一個類定義並返回一個生成器函數以從該類創建對象。典型的用法是這樣的:

myClass <- setClass("myClass", slots= ...., contains =....)

其中第一個參數是新類的名稱,如果提供,參數 slots=contains= 指定新類和新類應繼承的現有類中的槽。對 setClass() 的調用通常可以在包的源代碼中找到;加載包時,該類將在包的命名空間中定義。用類名指定生成器函數對用戶來說很方便,但不是必需的。

用法

setClass(Class, representation, prototype, contains=character(),
         validity, access, where, version, sealed, package,
         S3methods = FALSE, slots)

參數

Class

類的字符串名稱。

slots

新類中插槽的名稱和類。該參數必須在調用中通過名稱 slots= 提供,以便與不再推薦的其他參數向後兼容。

參數必須是帶有名稱屬性的向量,名稱是新類中插槽的名稱。向量的每個元素指定一個現有的類;相應的槽必須來自該類或其子類。通常,這是命名類的字符向量。向量的元素作為類表示對象也是合法的,如 getClass 返回的那樣。

作為限製情況,參數可以是未命名的字符向量;這些元素被視為插槽名稱,並且所有插槽都具有不受限製的類 "ANY"

contains

一個向量,指定該類應繼承的現有類。新類將具有超類的所有槽,對這些槽的類具有相同的要求。該參數必須在調用中通過名稱 contains= 提供,以便與不再推薦的其他參數向後兼容。

請參閱“虛擬類”部分了解特殊超類 "VIRTUAL"

prototype, where, validity, sealed, package

這些論點目前是允許的,但或者它們不太可能有用,或者有首選的現代替代方案。

prototype :為該類中的槽提供默認數據的對象。更靈活的方法是為 initialize() 編寫一個方法。

where:提供存儲定義的環境。不應使用:對於出現在包源代碼中的setClass() 的調用,定義將存儲在包的命名空間中。

validity :為此類中的對象提供validity-checking 方法。為了使代碼更清晰,請使用對 setValidity() 的單獨調用。

sealed :如果 TRUE ,則類定義將被密封,以便對該類名再次調用 setClass 將失敗。但加載命名空間後,定義會自動密封,因此不需要顯式密封。

package :為類提供可選的包名稱,但類屬性應該是在其中分配類定義的包,默認情況下也是如此。

representation, access, version, S3methods

所有這些參數從 3.0.0 版本開始已棄用R並且應該避免.

representation 是從 S 繼承的參數,其中包括 slotscontains ,但後兩個參數的使用更清晰,建議使用。

包含 accessversion 是為了與 S-Plus 曆史兼容,但會被忽略。

S3methods是一個標誌,指示將編寫涉及該類的old-style方法;現在被忽略了。

一個適合從類創建對象的生成器函數會以不可見的方式返回。對此函數的調用會生成對該類的new 的調用。該調用采用任意數量的參數,這些參數將傳遞給初始化方法。如果沒有為該類或其超類之一定義 initialize 方法,則默認方法需要具有插槽之一名稱的命名參數和來自所包含的類之一的對象的未命名參數。

通常,為了編程清晰起見,生成器函數會被分配類的名稱。這不是必需的,類中的對象也可以直接從 new 生成。生成器函數的優點是調用稍微簡單和清晰,並且調用將包含類的包名稱(如果來自不同包的兩個類具有相同名稱,則消除任何歧義)。

如果該類是虛擬類,則嘗試從生成器或 new() 生成對象將導致錯誤。

基本用途:槽和繼承

除類名之外的兩個基本參數是 slotscontains ,它們定義顯式槽和繼承(超類)。這些參數一起定義了該類的對象中的所有信息;即所有槽的名稱以及每個槽所需的類。

類的名稱決定哪些方法直接應用於該類的對象。超類信息指定通過繼承間接應用哪些方法。方法選擇中的繼承請參見Methods_Details

類定義中的槽將是由 slots 直接指定的所有槽和所有包含的類中的所有槽的並集。隻能有一個具有給定名稱的插槽。類可以覆蓋具有給定名稱的槽的定義,但前提是新指定的類是繼承類的子類。例如,如果包含的類有一個槽 a 和類 "ANY" ,則子類可以指定 a 和類 "numeric" ,但如果該槽的原始規範是類 "character" ,則新調用setClass 會產生錯誤。

不允許插槽名稱 "class""Class"。還有其他具有特殊含義的插槽名稱;這些名稱以 "." 字符開頭。為了安全起見,您應該定義自己的所有插槽,其名稱以字母字符開頭。

一些繼承的類將被特殊對待——對象類型、S3 類和一些特殊情況——無論是直接繼承還是間接繼承。請參閱接下來的三節。

虛擬課程

存在無法為其創建實際對象的類,即虛擬類。

虛擬課堂最常見和最有用的形式是階級聯盟,在調用中定義的虛擬類setClassUnion()而不是調用給setClass()。此調用列出了會員聯合的子類擴展了新類。在簽名中使用類聯合編寫的方法可以與任何成員類中的對象一起使用。類聯合可以包含其定義被密封的成員類,包括基本類R數據類型。

當僅提供 Class 參數(無槽或超類)或當 contains= 參數包含特殊類名 "VIRTUAL" 時,對 setClass() 的調用也將創建一個虛擬類。

在後一種情況下,虛擬類可能包含槽來提供一些常見行為,而無需完全定義對象 - 請參閱類traceable 作為示例。請注意,"VIRTUAL" 不會延續到子類;包含虛擬類的類本身並不自動是虛擬的。

從對象類型繼承

除了包含其他 S4 類之外,類定義還可以包含 S3 類(請參閱下一節)或內置 R pseudo-class——其中一個R對象類型或特殊類型之一R偽類"matrix""array"。一個類最多可以直接或間接包含一種對象類型。當它出現時,包含的類確定該類的“data part”。這顯示為pseudo-slot,".Data"和 可以被視為一個槽,但實際上確定該槽中對象的類型。

新類中的對象嘗試繼承所包含類型的內置行為。正常情況下R數據類型包括向量、函數和表達式,實現相對簡單。對於任何物體x從課堂上,typeof(x)將是包含的基本類型;和一個特殊的pseudo-slot,.Data,將與相應的類別一起顯示。請參閱"numWithId"下麵的例子。

類也可以繼承自 "vector""matrix""array" 。這些對象的數據部分可以是任何矢量數據類型。

對於不包含這些類型或類之一的任何類的對象, typeof(x) 將是 "S4"

一些R數據類型的行為不正常,因為它們是非本地引用或其他不重複的對象。示例包括對應於類的示例"environment","externalptr", 和"name"。這些不能是具有用戶定義類(S4 或 S3)的對象的類型,因為設置屬性會覆蓋所有上下文中的對象。可以通過將繼承的對象存儲在保留槽中的間接機製來定義從此類類型繼承的類,".xData"。請參閱類的示例"stampedEnv"以下。來自此類的對象確實不是有一個".Data"pseudo-slot。

對於大多數計算,這些類的行為是透明的,就好像它們直接從異常類型繼承一樣。 S3 方法調度和相關的 as. 類型 () 函數應該正常運行,但直接使用對象類型的代碼則不會。例如, as.environment(e1) 將按預期與 "stampedEnv" 類一起工作,但 typeof(e1)"S4"

從S3類繼承

Old-style S3 類沒有正式定義。當對象的類屬性包含被視為類名的字符串時,對象就是“from”類。

將此類類與正式類和方法一起使用必然是一件有風險的事情,因為無法保證對象的內容或繼承方法的一致性。鑒於此,仍然可以定義一個從 S3 類繼承的類,前提是該類已注冊為舊類(請參閱 setOldClass )。

從廣義上講,S3 和 S4 方法分派都嘗試在任一係統中對繼承表現得明智。給定一個 S4 對象,S3 方法調度和 inherits 函數應使用 S4 繼承信息。給定一個 S3 對象,S4 泛型函數將使用 S3 繼承調度 S4 方法,前提是已通過 setOldClass 聲明了繼承。有關詳細信息,請參閱setOldClass 和參考文獻的第 10.8 節。

課程和套餐

類定義通常屬於包(但也可以在全局環境中定義,通過評估命令行上或源自命令行的文件中的表達式)。相應的包名稱是類定義的一部分;也就是說,classRepresentation 對象的一部分保存該定義。因此,對於大多數用途來說,兩個具有相同名稱的類可以存在於不同的包中。

當在 setClass 調用中為槽或超類提供類名時,將從當前包的命名空間中查找相應的類定義,假設相關調用直接出現在包的源代碼中,因為它應該避免歧義。類定義必須已在此包中、包的DESCRIPTIONNAMESPACE 文件的導入指令中或在方法包定義的基本類中定義。 (‘methods’ 包必須包含在任何使用 S4 方法和類的包的導入指令中,以滿足 "CMD check" 實用程序的要求。)

如果一個包從不同的包導入兩個同名的類,則 name 參數的 packageSlot 需要設置為特定類的包名稱。這種情況應該很少見。

例子


## A simple class with two slots
track <- setClass("track", slots = c(x="numeric", y="numeric"))
## an object from the class
t1 <- track(x = 1:10, y = 1:10 + rnorm(10))

## A class extending the previous, adding one more slot
trackCurve <- setClass("trackCurve",
		slots = c(smooth = "numeric"),
		contains = "track")

## an object containing a superclass object
t1s <- trackCurve(t1, smooth = 1:10)

## A class similar to "trackCurve", but with different structure
## allowing matrices for the "y" and "smooth" slots
setClass("trackMultiCurve",
         slots = c(x="numeric", y="matrix", smooth="matrix"),
         prototype = list(x=numeric(), y=matrix(0,0,0),
                          smooth= matrix(0,0,0)))

## A class that extends the built-in data type "numeric"

numWithId <- setClass("numWithId", slots = c(id = "character"),
         contains = "numeric")

numWithId(1:3, id = "An Example")

## inherit from reference object of type "environment"
stampedEnv <- setClass("stampedEnv", contains = "environment",
                       slots = c(update = "POSIXct"))
setMethod("[[<-", c("stampedEnv", "character", "missing"),
   function(x, i, j, ..., value) {
       ev <- as(x, "environment")
       ev[[i]] <- value  #update the object in the environment
       x@update <- Sys.time() # and the update time
       x})


e1 <- stampedEnv(update = Sys.time())

e1[["noise"]] <- rnorm(10)


參考

Chambers, John M. (2016) Extending R, Chapman & Hall. (Chapters 9 and 10.)

也可以看看

Classes_Details 用於類的一般討論,Methods_Details 用於方法的類似討論,makeClassRepresentation

相關用法


注:本文由純淨天空篩選整理自R-devel大神的英文原創作品 Create a Class Definition。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。