14

S3 クラスと S4 クラスの両方を実装する必要がある汎用関数を定義する良い方法は何ですか? 私はこのようなものを使用しています:

setGeneric("myfun", function(x, ...){  
    standardGeneric("myfun");
});

setMethod("myfun", "ANY", function(x, ...) {
    if(!isS4(x)) {
        return(UseMethod("myfun"));
    }
    stop("No implementation found for class: ", class(x));
});

これは成功します:

myfun.bar <- function(x, ...){
    return("Object of class bar successfully dispatched.");
}
object <- structure(123, class=c("foo", "bar"));
myfun(object)

これを達成するための「ネイティブ」な方法はありますか?を使用して S3 クラスの S4 メソッドを定義できることはわかっていますがsetOldClass、この方法では、オブジェクトに複数のクラスがある場合に S3 メソッドのディスパッチが失われます。例 (クリーン セッションの場合):

setGeneric("myfun", function(x, ...){  
    standardGeneric("myfun");
});

setOldClass("bar")
setMethod("myfun", "bar", function(x, ...){
    return("Object of class bar successfully dispatched.");
});

object <- structure(123, class=c("foo", "bar"));
myfun(object)

の 2 番目のクラス (objectこの場合barは ) が無視されるため、これは失敗します。fooと の間で正式な S4 継承を定義することでおそらくこれを修正できますbarが、私のアプリケーションではmyfun.bar、 class を使用して S3 オブジェクトをそのまま使用したいと考えていますbar

いずれにせよ、物事は混乱しています。これは一般的な問題だと思います。おそらくこれを行うためのより良い方法がありますか?

4

1 に答える 1

19

?Methods のセクション「S3 ジェネリック関数のメソッド」では、S3 ジェネリック、S4 クラスの S3 スタイル メソッド、および S4 メソッド自体を提案しています。

setClass("A")                    # define a class

f3 <- function(x, ...)           # S3 generic, for S3 dispatch    
    UseMethod("f3")
setGeneric("f3")                 # S4 generic, for S4 dispatch, default is S3 generic
f3.A <- function(x, ...) {}      # S3 method for S4 class
setMethod("f3", "A", f3.A)       # S4 method for S4 class

S3 クラスをディスパッチするには、S3 ジェネリックが必要です。

setGeneric() は f3 (つまり、S3 ジェネリック) をデフォルトとして設定し、f3,ANY-method は実際には S3 ジェネリックです。「ANY」はクラス階層のルート (のようなもの) にあるため、S4 メソッドが存在しないオブジェクト (S3 オブジェクトなど) はすべて S3 ジェネリックになります。

S4 クラスの S3 ジェネリックの定義は、ヘルプ ページ ?Methods で説明されています。おおよそ、S3 は S4 メソッドについて認識していないと思います。そのため、S3 ジェネリックを呼び出した場合 (たとえば、パッケージが S3 f3 については知っているが S4 f3 については認識していないパッケージ名前空間にあるため)、f3 ジェネリックS4 メソッドが見つかりません。私はただのメッセンジャーです。

于 2012-08-23T23:09:42.077 に答える