2012-08-24 7 views
7

this 관련 질문이지만 약간 다르지만 희망적으로 더 명확합니다.S3 메소드에 대한 S3 스타일 디스패치 (공식 메소드 정의 사용)

나는, 그러나 파견에 대한 끔찍한 S3 점 명명-방식에 의존하지 않고 정식 S4 및 S3 클래스 모두를위한 방법을 등록하는 깨끗한 방법을 찾고 있어요. 예 :

setClass("foo"); 
setClass("bar"); 

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

setMethod("test", "bar", function(x, ...){ 
    return("success (bar)."); 
}); 

obj1 <- 123; 
class(obj1) <- "bar"; 
test(obj1); 

이 예는 우리가 대단한 기능 test.bar를, 이름을 할 필요없이, 클래스 bar의 S3 객체에 대한 test 방법을 등록 할 수있는 방법을 보여줍니다. 그러나이 방법으로 메소드를 등록하는 경우 제한은 오브젝트의 첫 번째 S3 클래스로만 디스패치됩니다. 예컨대는 :

obj2 <- 123; 
class(obj2) <- c("foo", "bar"); 
test(obj2); 

이 작동하지 않는, S4 방법 파견은 클래스 foo와 그 슈퍼 클래스를 시도 때문이다. foo에 대한 적절한 방법이 발견되지 않으면 bar에 대해 test 메서드를 자동으로 선택하도록이 예제를 어떻게 확장 할 수 있습니까? 예 : S3 스타일을 디스패치하지만 모든 것을 명명하는 데 돌아 가지 않고도 test.footest.bar?

요약하면 : 공식 메소드 디스 패칭을 사용하는 일반 함수를 만드는 방법은 물론 여러 클래스가있는 S3 객체에 대한 객체의 두 번째, 세 번째 등의 클래스로 대체하는 방법입니다.

setOldClass(c("foo", "bar")) 

setGeneric("test", function(x, ...)standardGeneric("test")) 
setMethod("test", "bar", function(x, ...)return("success (bar).")) 

답변

2

당신은 방법

test = function(x, ...) UseMethod("test") 

setGeneric("test") 

.redispatch = function(x, ...) 
{ 
    if (is.object(x) && !isS4(x) && length(class(x)) != 1L) { 
     class(x) = class(x)[-1] 
     callGeneric(x, ...) 
    } else callNextMethod(x, ...) 
} 

setMethod(test, "ANY", .redispatch) 

을 쓸 수 그러나 나는 개인적으로이 방법 S3과 S4를 함께 사용하지 것이다 :

+0

예 저는 비슷한 것을 해오 고 있습니다. 하지만 실제로 x의 클래스 속성을 변경하는 것은 바람직하지 않은 부작용을 가져올 수 있습니다 ... 객체 자체를 수정하지 않고도 다음 메소드로 전달할 수있는 방법이 있습니까? – Jeroen

+0

답변이 없습니다. 제 생각에 S3 클래스 'bar'에서 작동하는 'bar'에 대한 S4 메소드는 구현 실수 였고 매우 불안정한 기반에서 복잡한 구조를 구축하고 있다고 생각합니다. –

3

?setOldClass 대답을 줄 것이다.

+0

이것은 정확히 내가 원하는 것이 아닙니다. 그것은 "foo"와 "bar"클래스 사이에 공식적인 상속이 필요합니다. 가능한 모든 클래스 x에 대해 x와 bar 사이의 상속을 선언 할 필요없이 x = anything에 대해 class = [x, "bar"]가있는 임의의 객체에 대해 작업 할 수 있습니다. 다른 누군가가 [ "zoo", "bar"] 클래스를 가진 객체를 생성했다면'test()'함수는 "bar"에 대한 메소드를 선택할만큼 똑똑해야합니다. – Jeroen