R语言的S3类与泛型函数

时间:2021-07-30 15:39:56
实际上,初学R语言的时候,对于”.“(点号)的用法感到很不适应。例如函数被命名为as.data.frame,或者使用点号来对变量进行命名。实际上点号与泛型函数有很强的联系,所以当我个人编码的时候,从来不使用点号来命名变量,例如我不会将变量命名为best.model,而是将变量命名为bestModel。我觉得这样的风格应该是最明确的,因为将其与泛型函数划清了界限。
此外函数的命名,我一般也使用下划线作为连接符,例如命名为find_value,而不会使用find.value

现在我们来看看泛型函数与R的S3类之间有什么关系。在R中,泛型函数在被调用的时候,会根据输入变量的class属性来做出合适的反应。例如plot就是一个泛型函数,对于大部分的对象来x说,你都可以调用plot(x)来绘图,尽管你可能并不了解x的结构和特征。这样就给用户带来了极大的方面,免于许多记忆。下面,我们将plot函数与一个自定义的class关联起来。

S3类的定义比较随意。例如,如果我们定义一个列表:

x <- list(a = 1:10, b = 11:20)
class(x)

此时,x只是一个一般的list,这个list有两个元素,为等长的向量。现在,我们可以指定其class属性为'pair'(随便定义的):

class(x) <- 'pair'
class(x)
 

如果我们需要定义一个函数对这个类进行绘图,例如我们想通过绘图的方式比较这两个向量,我们可以使用泛型函数的方法。我们定义方法plot.pair:

plot.pair <- function(obj) {
mi <- min(c(x$a, x$b))
ma <- max(c(x$a, x$b))
plot(x$a, type = 'o', col = 'blue', ylim = c(mi, ma))
lines(x$b, type = 'o', col = 'red')
}

现在,如果我们输入:

plot(x)

程序显示:
R语言的S3类与泛型函数

如果我们想查看泛型函数plot相关的所有的方法,使用:

methods(plot)

程序显示:

 [1] plot.acf*           plot.data.frame*    plot.decomposed.ts*
 [4] plot.default        plot.dendrogram*    plot.density      
 [7] plot.ecdf           plot.factor*        plot.formula*     
[10] plot.function       plot.hclust*        plot.histogram*   
[13] plot.HoltWinters*   plot.isoreg*        plot.lm           
[16] plot.medpolish*     plot.mlm            plot.pair         
[19] plot.ppr*           plot.prcomp*        plot.princomp*    
[22] plot.profile.nls*   plot.spec           plot.stepfun      
[25] plot.stl*           plot.table*         plot.ts           
[28] plot.tskernel*      plot.TukeyHSD     

   Non-visible functions are asterisked

如果我们想查看类pair所有的方法,使用:

methods(class = 'pair')

程序显示:

[1] plot.pair

 

事实上,如果在命令行键入plot,会发现plot函数只有下面短短的几行:


function (x, y, ...)
UseMethod("plot")
<bytecode: 0x07a709a0>
<environment: namespace:graphics>


也就是说,当我们输入plot(x)时,函数会调用UseMethod("plot")命令,此时函数UseMethod会根据x的类别名称pair查找函数plot.pair,而plot.pair就是我们在上面定义的方法。如果找不到特定的方法,则默认的plot.default将会被调用。