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


R setOldClass 注冊舊式 (S3) 類和繼承


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

說明

將old-style(又名“S3”)類注冊為正式定義的類。簡單的用法將采用以下形式:

setOldClass(Classes)

其中 Classes 是字符向量,它是 S3 對象的 class 屬性。在包的代碼中調用 setOldClass() 允許將該類用作正式 (S4) 類和方法簽名中的槽(請參閱 Methods_for_S3 )。正式類還可以包含已注冊的 S3 類(有關詳細信息,請參閱S3Part)。

如果 S3 類具有一組已知的屬性,則可以通過調用 setOldClass() 中的 S4Class= 指定等效的 S4 類;請參閱“Known Attributes”部分。

用法

setOldClass(Classes, prototype, where, test = FALSE, S4Class)

參數

Classes

一個字符向量,給出 S3 類的名稱,它們將出現在 S3 計算中 class 屬性賦值的右側。

除了 S3 類之外,如果已知 S3 類要求其數據采用該形式,則還可以指定對象類型或其他有效數據部分。

S4Class

(可選)S4 類的類定義或類名稱。新類將具有該類的所有槽和其他屬性,以及 Classes 參數中多個名稱隱含的任何 S3 繼承。請參閱下麵的“具有已知屬性的 S3 類”部分。

prototype, where, test

這些參數目前是允許的,但在典型應用中不推薦。

prototype :用作原型的可選對象。如果 S3 類不是VIRTUAL(默認),則優先使用S4Class=

where :存儲類定義的位置。應該是應用程序包中正常使用的默認值(包命名空間)。

test :標誌,如果是 TRUE ,則安排顯式測試每個對象的繼承,如果 S3 類可以有一組不同的類字符串,並且具有相同的第一個字符串,則需要。這樣的類本質上是畸形的,而且很少見,應該避免。

細節

Classes 中的名稱(或每個名稱)將被定義為 S4 類,擴展類 oldClass ,它是所有 old-style 類的 ‘root’ 。其類屬性中具有多個名稱的 S3 類將具有與正式類相應的繼承。請參閱"mlm" 示例。

S3 類沒有正式定義,因此也沒有正式定義的槽。如果沒有提供 S4 類作為模型,則創建的類將是虛擬類。如果虛擬類(任何虛擬類)用於另一個類中的槽,則該類的初始化方法需要在該槽中放置合法的內容;否則它將被設置為 NULL

有關混合 S3 和 S4 方法的方法分派和繼承的詳細信息,請參閱Methods_for_S3

某些 S3 類不能表示為 S4 類和超類的普通組合,因為類屬性中具有相同初始字符串的對象可以有不同的字符串。幸運的是,這樣的課程很少見。它們違反了麵向對象編程的基本思想,應該避免。如果您必須處理它們,仍然可以將此類類注冊為 S4 類,但現在必須驗證每個對象的繼承,並且您必須使用參數 test=TRUE 調用 setOldClass

預定義的舊類

標準 R 發行版中許多廣泛使用的 S3 類都是預先定義的,可與 S4 一起使用。這些不需要在包中顯式聲明(盡管這樣做沒有什麽壞處)。

列表.OldClassesList 包含由方法包定義的old-style 類。列表的每個元素都是一個字符向量,如果包含繼承,則具有多個字符串。創建methods包時,列表中的每個元素都被傳遞給setOldClass;因此,這些類可以在 setMethod 調用中使用,並具有列表所暗示的繼承。

具有已知屬性的 S3 類

如果保證 S3 類具有已知類的某些屬性(其中與槽一樣,“known” 表示該屬性是指定類的對象或該類的子類),則可以對 S3 類進行進一步規範。 。

在這種情況下,對setOldClass()的調用可以提供表示已知結構的S4類定義。由於 S4 槽被實現為屬性(很大程度上正是出於這個原因),因此可以在 S4 類的表示中指定已知屬性。通常的技術是創建具有所需結構的 S4 類,然後提供類名稱或定義作為參數 S4Class=setOldClass()

請參閱下麵示例中的類 "ts" 的定義以及參考文獻第 10.2 節中的 data.frame 示例。對 setClass 的調用來創建 S4 類可以使用相同的類名,如此處所示,隻要對 setOldClass 的調用位於同一包中即可。為了清楚起見,它應該是同一文件中的下一個表達式。

在示例中,我們定義"ts"作為帶有數字槽的向量結構"tsp"。該定義的有效性依賴於該類的所有 S3 代碼都與該定義一致的斷言;具體來說,所有"ts"對象將表現為向量結構並且將具有數字"tsp"屬性。我們相信這對於所有基本代碼都是如此R,但與 S3 類一樣,無法保證。

如果斷言 S3 類的行為與虛擬超類一致(在示例中,斷言時間序列對象與 structure 類一致),則 S4 類定義可以具有虛擬超類(如 "ts" 情況)。

S3 類未能實現其斷言行為通常不會得到糾正,因為 S3 類本質上沒有定義,並且由此產生的無效 S4 對象可能會導致各種痛苦。許多 S3 類不是已知槽的候選者,或者是因為無法保證屬性的存在或類(例如,數組中的 dimnames,盡管這些甚至不是 S3 類),或者是因為該類使用列表的命名組件而不是屬性(例如 "lm" )。有時丟失的屬性不能表示為槽,甚至不能假裝它與類 "NULL" 一起存在,因為與槽不同,屬性不能具有值 NULL

然而,通常可以容忍的一種不規則行為是有選擇地向那些保證存在的屬性添加其他屬性(例如, model.frame 返回的 "data.frame" 對象中的 "terms" )。 validObject 的有效性檢查忽略額外屬性;即使將來加強此檢查,擴展 S3 類的類也可能會被免除,因為額外的屬性非常常見。

例子



require(stats)

## "lm" and "mlm" are predefined; if they were not this would do it:
## Not run: 
setOldClass(c("mlm", "lm"))
## End(Not run)

## Define a new generic function to compute the residual degrees of freedom
setGeneric("dfResidual",
  function(model) stop(gettextf(
    "This function only works for fitted model objects, not class %s",
                                class(model))))

setMethod("dfResidual", "lm", function(model)model$df.residual)

## dfResidual will work on mlm objects as well as lm objects
myData <- data.frame(time = 1:10, y = (1:10)^.5)
myLm <- lm(cbind(y, y^3)  ~ time, myData)



## two examples extending S3 class "lm": class "xlm" directly
## and "ylm" indirectly
setClass("xlm", slots = c(eps = "numeric"), contains = "lm")
setClass("ylm", slots = c(header = "character"), contains = "xlm")
ym1 = new("ylm", myLm, header = "Example", eps = 0.)
## for more examples, see ?\link{S3Class}.




## Not run: 
## The code in R that defines "ts" as an S4 class
setClass("ts", contains = "structure", slots = c(tsp = "numeric"),
         prototype(NA, tsp = rep(1,3)))
       # prototype to be a legal S3 time-series
## and now registers it as an S3 class
setOldClass("ts", S4Class = "ts", where = envir)

## End(Not run)

參考

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

也可以看看

setClass , setMethod

相關用法


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