8

というクラスがある場合、関数fooをオーバーロードするのは簡単ですsummary

summary.foo = function(x, ...) print("bar")

sdただし、この手法は関数では機能しません。つまり、

> bar = createFooClass()
> sd.foo = function(x, ...) print("Hi")
> sd(bar)
  error: is.atomic(x) is not TRUE

この関数をオーバーロードする正しい方法は何ですか?

4

3 に答える 3

7

非ジェネリック関数をハイジャックし、それを(S3)ジェネリックにして、元のバージョンをデフォルトバージョンに設定することができます。例えば:

## make an S3 generic for sd
sd <- function(x, ...) UseMethod("sd")
## take the usual definition of sd,
## and set it to be the default method
sd.default <- stats::sd
## create a method for our class "foo"
sd.foo = function(x, ...) print("Hi")

これがパッケージに含まれている場合の最後のステップは、パッケージチェックに合格できるようにするための...引数を追加することです。sd.default

formals(sd.default) <- c(formals(sd.default), alist(... = ))

与える:

> args(sd.default)
function (x, na.rm = FALSE, ...) 
NULL
> args(stats::sd)
function (x, na.rm = FALSE) 
NULL

これにより、目的の動作が得られます。

> bar <- 1:10
> sd(bar)
[1] 3.027650
> class(bar) <- "foo"
> sd(bar)
[1] "Hi"

これは、R拡張機能の作成マニュアルのセクション7.1に記載されています。

于 2011-01-18T23:26:48.947 に答える
3

の新しいジェネリックを定義する必要がありますsd

S4を使用するのが最も簡単な方法です。これは、デフォルトの「sd」メソッドを自動的に処理するためです。

setClass("foo", list(a = "numeric", names = "character"))

setGeneric("sd")

setMethod("sd", "foo", 
          function(x,  na.rm = FALSE){
              print("This is a foo object!")
              callNextMethod(x@a)
              })

tf <- new("foo", a = 1:10)
sd(tf)
#[1] "This is a foo object!"
#[1] 3.027650
于 2011-01-18T22:00:06.830 に答える
1

sd()--- 内部で効果的にディスパッチするコードを見てください。つまり、汎用関数ではなく、昔ながらの通常の関数です。

sd()最も簡単なのは、クラス foo で分岐 するように変更することです。

于 2011-01-18T19:55:32.237 に答える