f <- function() 1
g <- function() 2
class(g) <- "function"
class(f) ## "function"
class(g) ## "function"
length.function <- function(x) "function"
length(f) ## 1
length(g) ## "function"
答案 0 :(得分:5)
首先,length
不是典型的通用函数,而是“Internal Generic Function”。您可以通过查看其定义来看到这一点:
> length
function (x) .Primitive("length")
将其与典型的通用函数进行比较:
> print
function (x, ...)
UseMethod("print")
<bytecode: 0x116ca6f90>
<environment: namespace:base>
length
直接调用.Primitive
,然后如果它不处理调用本身就可以调度;典型的方法是直接调用UseMethod
,它只处理调度。另请注意,没有length.default
函数,因为.Primitive
调用中的代码执行此操作:
> methods("length")
[1] length.function length.pdf_doc* length.POSIXlt
当内部Generic查看用户定义的方法以及何时只使用内部方法时,我不确定它是否已完全定义;我认为一般的想法是,对于用户/包定义(有效,非核心)类,将使用提供的方法。但是,压倒内部课程可能会也可能不会起作用。
此外(尽管对于这种情况并不严格相关),即使对于典型的通用方法,文档也不明确,当隐式派生类而不是作为属性给出时应该发生什么。首先,class()
报告是事物的融合。来自class
帮助页面:
许多R对象都有
class
属性,一个字符向量给出了对象继承的类的名称。如果对象没有class属性,则它具有隐式类"matrix"
,"array"
或mode(x)
的结果(除了整数向量具有隐式类"integer"
)
尽管class
为f
和g
返回了同样的内容,但它们并不相同。
> attributes(f)
$srcref
function() 1
> attributes(g)
$srcref
function() 2
$class
[1] "function"
现在,这里是模棱两可的地方。在(至少)2个地方讨论了方法调度:class
帮助页面和UseMethod
帮助页面。 UseMethod
说:
当一个函数调用
UseMethod("fun")
应用于具有类属性c("first", "second")
的对象时,系统会搜索一个名为fun.first
的函数,如果找到它,则将其应用于该对象。如果没有找到这样的函数,则尝试使用名为fun.second
的函数。如果没有类名生成合适的函数,则使用函数fun.default
(如果存在)或导致错误。
虽然class
说:
当将通用函数fun应用于具有类属性
c("first", "second")
的对象时,系统将搜索名为fun.first
的函数,如果找到它,则将其应用于对象。如果未找到此类函数,则尝试使用名为fun.second
的函数。如果没有类名生成合适的函数,则使用函数fun.default
(如果存在)。如果没有class属性,则尝试隐式类,然后使用默认方法。
真正的区别在于class
页面的最后一句话UseMethod
没有。 UseMethod
没有说明如果没有class
属性会发生什么; class
表示隐式类用于调度。您的代码似乎表明class
中记录的内容不正确,因为length.function
会调用g
。
当没有类属性时,方法调度中发生的真正的可能需要检查源代码,因为文档似乎没有帮助。