为什么predict
不是通用函数? isGeneric('predict')
为FALSE
,但isGeneric('summary')
和isGeneric('print')
为TRUE
。他们都有方法,可以列出methods('predict')
等?因此predict
不是here描述的通用函数(从class
看也很明显),但仍会根据传递给它的对象调度方法(例如predict.lm
或{ {1}})。那么R调度方法有不同的方式吗?如何测试函数是否具有方法,以便上述所有示例都为真?是的,我可以测试predict.glm
的长度,但是对没有方法的函数会产生警告。
答案 0 :(得分:15)
首先,你的测试中没有一个是通用的:
> isGeneric('predict')
[1] FALSE
> isGeneric('summary')
[1] FALSE
> isGeneric('print')
[1] FALSE
让我们再试一次......
> isGeneric("summary")
[1] FALSE
> require(sp)
Loading required package: sp
> isGeneric("summary")
[1] TRUE
这里发生了什么?好吧,isGeneric
只测试S4泛型函数,当我启动R summary
时是一个S3泛型函数。如果一个包想要使用S4方法和类,并且已经存在S3泛型函数,那么它可以创建一个S4泛型。
所以,最初summary
是:
> summary
function (object, ...)
UseMethod("summary")
<bytecode: 0x9e4fc08>
<environment: namespace:base>
这是一个S3泛型。我得到了sp
包......
> require(sp)
Loading required package: sp
> summary
standardGeneric for "summary" defined from package "base"
function (object, ...)
standardGeneric("summary")
<environment: 0x9f9d428>
Methods may be defined for arguments: object
Use showMethods("summary") for currently available ones.
现在summary
是S4标准通用。
S3泛型方法通常通过调用{generic}.{class}
来发送,这是UseMethod("summary")
在S3 summary
泛型函数中的作用。
如果要测试函数是否具有特定类的方法,那么您可能必须测试它是否具有S4方法(使用S4方法元数据的函数)和S3方法(通过查找名为{generic}.{class}
,例如summary.glm
。
太棒了?
答案 1 :(得分:2)
我对S3泛型的一般理解来自from the R Language manual,我在其中认为函数func
在不调用UseMethod
的情况下不能成为泛型。因此,如果没有任何精美的软件包,您可以使用以下gist:
isFuncS3Generic <- function(func) {
funcBody <- body(func)
sum(grepl(pattern="UseMethod", x=funcBody)) != 0
}
编辑:使用石蕊测试:
> isFuncS3Generic(print)
[1] TRUE
> isFuncS3Generic(predict)
[1] TRUE
> isFuncS3Generic(summary)
[1] TRUE
> isFuncS3Generic(glm)
[1] FALSE
@Hadley,我不确定为什么这是一个难题。你介意详细说明吗?