7.1 S3方法

7.1 S3方法

S3方法和白色的書一致.

在R的觀念中,一個對象的屬性可以是一組異常豐富的數據對象.在面向對象系統中,S3方法以clsss屬性爲驅動.它是一個可選的系統.只有當一個對象擁有class屬性時,S3方法纔會真正起到作用.

有一些函數是泛型的.例如print(),plot(),summary().這些函數查詢第一個入參是否帶有class屬性.如果第一個入參擁有一個class屬性,那麼這個泛型函數就會搜尋一個它擁有的能夠匹配該class屬性的具體函數.如果匹配成功,這個具體函數就會被調用.如果不存在該class類型的具體函數,那麼默認函數會被調用.

我們來個具體的.函數lm()(線性模型)返回一個”lm”類型的對象.關於此方法的輸出函數有print.lm()和print.default().lm()調用的輸出由print.lm()來輸出.1:10的結果輸出則由print.default()完成.

S3方法簡單而強大.對象被恰當地輸出,繪圖和彙總,用戶不用關心.用戶只需要知道print(),plot()和summary()就好了.

對於免費的午餐也會有一點開銷.print()是泛型的意味着你的所見並非所得(有時是這樣的).對於一個對象的輸出,你或許想要看到一個你想要的數字–比如說一個”R-squared”–但是你並不知道怎樣去獲得這個數字.如果你的神祕數字在obj,那麼你有一些方法去查找:

print.default(obj)
print(unclass(obj))
str(obj)  

前兩個假設對象沒有class,最後一個輸出對象的結構.你也可以這樣:

names(obj)

來查看這個對象包含的元素–這個可以提供給你對象的概觀.

7.1.1 泛型函數

有時一個新的使用者對median()會有一點點好奇並且想知道它是這麼工作的.然後情理之中,他會敲擊函數名稱去看看:

> median
function (x, na.rm = FALSE)
UseMethod("median")
<environment: namespace:stats>  

這個新的使用者就又問了,”怎樣我才能看到median()的函數代碼呢?”

答案是,”你已經看到它的代碼了.”又UseMethod()的出現可以證明median()是一個泛型函數.這個新用戶想問的是,”我怎樣才能找到median()的默認方法?”

最確切的方法是使用getS3method():

getS3method(’median’, ’default’)

7.1.2 方法

methods()列舉一個泛型函數的方法.可替代地如果輸入一個class,methods()就會列舉那些對此class提供方法的泛型函數.這個陳述需要一些限制:

  • 它會列舉當前對話所依附的方法.
  • 它以名字爲索引-它將列舉generic.class類型的對象.這是合理的聰明的,但是這也會愚蠢地列舉那些並不是真正的方法的對象.

median(當前對話情況下)的所有方法可以這樣獲得:

methods(median)

“factor”類的方法可以這樣獲得:

methods(class=’factor’)

7.1.3 繼承

類可以繼承自其它類.例如:

> class(ordered(c(90, 90, 100, 110, 110)))
[1] "ordered" "factor"   

“ordered”類繼承自”factor”類.Ordered因素是因素,但是不是所有的因素是ordered類.如果”ordered”有一個明確的泛型方法,那麼當函數調用第一個入參是是”ordered”類,這個方法將會被調用.然而,如果這裏沒有關於”ordered”類的此類方法,但是有關於”factor”類的此類的方法,那麼”factor”類的方法會被調用.

繼承應該基於對象結構上的相似性,而不是對象概念上的相似性.矩陣和數據框擁有相似的概念.矩陣是數據框的一個特例(所有列擁有相同的類型),因此在概念上繼承是有意義的.然而矩陣和數據框有完全不同的實現方法,因此繼承並沒有實際意義.繼承的作用是擁有重複使用代碼的能力.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章