class与typeof的区别, 通用函数如何用class信息判断确定具体调用

typeof相比class简单多了, 本文重点是class.

我确信, 这个主题中文比我写得好的博客可能不存在.

mode与typeof

先指出这两者的区别: typeof比mode精细. 比如function可以分为builtin和closure, 后面两者其实都是function, 参考.

再比如, 我在这篇博客(numeric与double)中提到, is.numeric对integer也会返回T. 而反之不会.

mode(1:5) # numeric
typeof(1:5) # integer

再次印证了typeof更精细.

更重要的是相同点: 它们都在说一回事: 数据如何在R中存储.

typeof会返回什么?
mode: character string naming an atomic mode or ‘"list"’ or ‘"expression"’ or (except for ‘vector’) ‘"any"’.  Currently, ‘is.vector()’ allows any type (see ‘typeof’) for ‘mode’, and when mode is not ‘"any"’, ‘is.vector(x, mode)’ is almost the same as ‘typeof(x) == mode’.

它的返回包括atomic类型(有哪6类, 写在后面)+list+expression(这些都是mode)

比如data.frame, 返回list.

但还有更复杂的:

builtin(basic函数和运算符), closure(函数), 两者区别我也不清楚. 但typeof作用于grep和matrix这些函数, 都是closure. 我只看到了两个返回是builtin的:

typeof(`+`)
typeof(class)

除此之外, 还有: NULL, special, environment, "S4": 如果是S4类

其它的很不常用, 可以看文档.

有哪些atomic类型

来自atomic的文档

The atomic modes are ‘"logical"’, ‘"integer"’, ‘"numeric"’ (synonym ‘"double"’), ‘"complex"’, ‘"character"’ and ‘"raw"’.

这6种

class

class与typeof完全不同, 关系不大, 它用于实现R中的OOP机制.

可以给class赋值, 可以是向量

比如

a=c(1,2)
class(a)<-c("abc","bce")
> class(a)
[1] "abc" "bce"
函数作用后会影响class
隐式class

If the object does not have a class attribute, it has an implicit class, notably ‘"matrix"’, ‘"array"’, ‘"function"’ or ‘"numeric"’ or the result of ‘typeof(x)’ (which is similar to ‘mode(x)’), but for type ‘"language"’ and ‘mode’ ‘"call"’, where the following extra classes exist for the corresponding function ‘call’s: ‘if’, ‘while’, ‘for’, ‘=’, ‘<-’, ‘(’, ‘{’, ‘call’.Note that ‘NULL’ objects cannot have attributes (hence not classes) and attempting to assign a class is an error.

也就是如果没有显示的class, 隐式class会根据dim和mode得到(比这个更复杂一些). 包括‘"matrix"’, ‘"array"’, ‘"function"’ or ‘"numeric", 以及typeof的结果.

隐式class不能由attr得到, 但可以由class()得到. 比如:

> class(grep)
[1] "function"
> attr(grep,"class")
NULL

由于隐式class与typeof在作用于向量时常常相等, 而让人误以为它们是类似的.

class与通用函数(gerneric function)调用的关系

通用函数其实就是看碟下菜, 对不同类型的输入实际上调用的是不同的函数, 最典型的代表就是summary. 对向量和lm返回完全不一样.

其原理与class密不可分.

Method dispatch takes place based on the class of the first argument to the generic function.

也就是说generic function根据第一个参数的class来决定怎么处理. 但到底怎么决定的?

When a generic function ‘fun’ is applied to an object with class attribute ‘c("first", "second")’, the system searches for a function called ‘fun.first’ and, if it finds it, applies it to the object. If no such function is found, a function called ‘fun.second’ is tried. If no class name produces a suitable function, the function ‘fun.default’ is used (if it exists). If there is no class attribute, the implicit class is tried, then the default method.

其实就是由class()输出的前两个决定. 先看第一个, 看看有没有function.first, 再看有没有第二个function.second. 都没有就是function.default, 这个function.default显然是由具体函数决定的.

比如summary与lm

> fit<-lm(weight~height,women)
> class(fit)
[1] "lm"

结果发现真的有个函数, summary.first.

class的文档还有很多内容, 但我也没兴趣. 如果有需要再看.

posted @ 2020-10-13 19:11  Tokubara  阅读(762)  评论(0编辑  收藏  举报