2011-07-22 6 views
2

スーパークラスfbのオブジェクトが存在しないクラス階層があります(仮想クラスを試しましたが、仮想クラスからオブジェクトを初期化できないという問題がありました)。さらに、同じスロットを持つ2つのサブクラス(foobar)があります。今、私はいくつかの値に基づいてサブクラスの1のオブジェクトを返すスーパークラスにinitializeメソッドを使用して、新しいオブジェクトを作りたい:明らか他のオブジェクトが返されるようにS4オブジェクトを初期化する方法はありますか?

setClass("fb", representation(x = "numeric")) 

setClass("foo", contains = "fb") 
setClass("bar", contains = "fb") 

setMethod("initialize", "fb", function(.Object, x) { 
    if (x < 5) class(.Object) <- "foo" 
    else class(.Object) <- "bar" 
    [email protected] <- x 
    .Object 
}) 

> new("fb", x = 3) 
Error in initialize(value, ...) : 
    initialize method returned an object of class "foo" instead of the required class "fb" 

(そしておそらく正当な理由で)Rはそれを許可していません。新しいオブジェクトを作成するときにメソッド内で必要なものを実現し、if-else構造を使用しない方法がありますか?

答えて

4

S4は、ライン内で色を付けるのに役立ちます。したがって、あなたのfbクラスは仮想でなければなりません。initializeメソッドは、.Objectのクラスを変更すべきではありません。条件付きのインスタンス化を行う関数fbを書くかもしれません。

setClass("fb", representation(x = "numeric", "VIRTUAL")) 
setClass("foo", contains = "fb") 
setClass("bar", contains = "fb") 

fb <- 
    function(x) 
{ 
    if (x < 5) new("foo", x=x) 
    else new("bar", x=x) 
} 

fb、ユーザにとってより便利なコンストラクタで、一般的に良いことと考えられ、その実装からあなたのクラス階層へのインターフェイスを分離します。

そして、それはS4 initializeメソッドに暗黙の制約価値がある何のため

は(あなたがfooを拡張しようとすると、それ以外の障害がある) new("foo")は(クラス名と newを呼び出すことなく、追加の引数)が動作してはならないということです。だから、initializeメソッドのためのパラダイムは、多くの場合、しかし全くinitializeメソッドの必要がない( initializeがちょうどスロット割当を行っている。この場合、のように)

setMethod(initialize, "foo", function(.Object, ..., x=1) { 
    .Object <- callNextMethod(.Object, ...) 
    [email protected] <- x 
    .Object 
}) 

のラインに沿っています。 ...の使用、xの位置付け(対応するnewの呼び出しで引数の名前を指定する必要があります)、およびデフォルト値の使用に注意してください。

関連する問題