R 및 객체 지향 프로그래밍


80

R에서는 어떤 식 으로든 객체 지향 프로그래밍이 가능합니다. 그러나 예를 들어 Python과 달리 객체 지향을 달성하는 방법에는 여러 가지가 있습니다.

내 질문은 :

R에서 이러한 OO 프로그래밍 방식을 구별하는 주요 차이점은 무엇입니까 ?

이상적으로 여기에있는 답변은 자신의 요구에 가장 적합한 OO 프로그래밍 방법을 결정하려는 R 프로그래머를위한 참고 자료가 될 것입니다.

따라서 저는 경험을 바탕으로 객관적인 방식으로 제시되고 사실과 참고 자료로 뒷받침되는 세부 사항을 요청하고 있습니다. 명확히에 대한 보너스 포인트 방법 이 방법은 표준 OO 관행에 매핑됩니다.


1
참조 클래스에 대한 정보 : stackoverflow.com/questions/5137199/…
Ari B. Friedman

감사합니다. 링크를 답변으로 다시 게시 할 수 있습니까? Reference 클래스가 무엇인지, 왜 S3 / S4 클래스와 관련하여 더 바람직한 지에 대한 간략한 요약을 포함 할 수 있다면 좋을 것입니다.
Paul Hiemstra

이 책에 대한 책이 John Chambers에 의해 나올 것이라고 작은 새가 내 귀에 속삭였습니다. 그러나 아무에게도 말하지 않는 그 ... ;-) 말했다
더크 Eddelbuettel

1
같은 약간의 BIRDY는 Refenence 클래스에 대한 좀 더 많은 정보와 아래의 답변을 붙여 넣을 수)
폴 Hiemstra

답변:


34

S3 클래스

  • 실제로 개체가 아니라 명명 규칙에 가깝습니다.
  • . 구문 : 예를 들어 인쇄, print호출 print.lm print.anova등. 찾을 수없는 경우print.default

S4 클래스

참조 클래스

프로토

  • ggplot2는 원래 proto로 작성되었지만 결국 S3를 사용하여 다시 작성됩니다.
  • 깔끔한 개념 (클래스가 아닌 프로토 타입)이지만 실제로는 까다로워 보입니다.
  • 다음 버전의 ggplot2가 멀어지는 것 같습니다.
  • 개념 및 구현에 대한 설명

R6 클래스

  • 참고로
  • S4 클래스에 의존하지 않음
  • " R6 클래스를 만드는 것은 필드와 메서드를 분리 할 필요가없고 필드 유형을 지정할 수 없다는 점을 제외하면 참조 클래스와 비슷합니다."

1
추가 할 다른 차이점이 있으면 자유롭게 편집하십시오. CW가 되어도 울지 않을 것입니다. :-)
Ari B. Friedman

3
잊지 마세요library("fortunes"); fortune("strait")
Ben Bolker 2011 년

1
S4 클래스에 대한 토론 : stackoverflow.com/questions/3602154/… . 일반적인 느낌은 그들이 이점을 제공하는 것보다 더 문제가 있다는 것입니다.
Paul Hiemstra

흥미롭게도 새로운 R6 클래스는 참조 클래스가 해당 번호를 사용하지 않음으로써 R5임을 암시 적으로 인정합니다. 논란이 시작되도록하십시오.
Ari B. Friedman

1
R5라는 이름은 원래 Reference Classes 개발자 이외의 사람들이 농담으로 사용했습니다. R6라는 이름은 "R5"에 대한 승인이지만 R5라는 이름이 공식적인 승인을 받았다는 의미는 아닙니다.
wch

19

3/8/12에 수정 : 아래 답변은 이후 삭제 된 원래 게시 된 질문에 대한 답변입니다. 내 대답에 대한 컨텍스트를 제공하기 위해 아래에 복사했습니다.

다른 OO 메소드가 예를 들어 Java 또는 Python에서 사용되는보다 표준적인 OO 메소드에 어떻게 매핑됩니까?


내 기여는 R의 OO 방법이 더 표준 OO 방법에 어떻게 매핑되는지에 대한 두 번째 질문과 관련이 있습니다. 과거에 이것에 대해 생각했듯이, 나는 Friedrich Leisch의 한 구절과 John Chambers의 두 구절로 계속해서 돌아 왔습니다. 둘 다 R의 OO와 유사한 프로그래밍이 다른 많은 언어와 다른 풍미를 갖는 이유를 잘 설명합니다.

먼저, "R 패키지 만들기 : 튜토리얼"의 Friedrich Leisch ( 경고 : PDF ) :

S는 상호 작용하고 객체 지향 시스템을 가지고 있기 때문에 드뭅니다. 클래스를 디자인하는 것은 분명히 프로그래밍이지만 S를 대화 형 데이터 분석 환경으로 유용하게 만들기 위해서는 기능적인 언어라는 것이 합리적입니다. C ++ 또는 Java 클래스와 같은 "실제"객체 지향 프로그래밍 (OOP) 언어에서 메서드 정의는 밀접하게 결합되어 있으며 메서드는 클래스의 일부입니다 (따라서 객체). 미리 정의 된 클래스에 대한 사용자 정의 메서드와 같은 점진적 상호 작용 추가를 원합니다. 이러한 추가는 데이터 세트를 분석하는 동안 명령 줄 프롬프트에서 즉석 에서조차도 언제든지 수행 할 수 있습니다. S는 객체 지향과 대화 형 사용 사이에서 타협을 시도하며, 타협이 도달하려는 모든 목표에 대해 최적이 아니지만 실제로는 놀랍도록 잘 작동하는 경우가 많습니다.

다른 구절은 John Chambers의 뛰어난 저서 "Software for Data Analysis" 에서 나옵니다 . ( 인용구에 대한 링크 ) :

OOP 프로그래밍 모델은 S 및 일부 다른 기능 언어가 클래스와 메서드를 지원하더라도 첫 번째 점을 제외하고는 S 언어와 다릅니다. OOP 시스템의 메서드 정의는 클래스에 국한됩니다. 메서드에 대해 동일한 이름이 관련되지 않은 클래스에 대해 동일한 것을 의미 할 필요는 없습니다. 반대로 R의 메서드 정의는 클래스 정의에 있지 않습니다. 개념적으로 그들은 일반 함수와 연관됩니다. 클래스 정의는 직접 또는 상속을 통해 메서드 선택을 결정할 때 입력됩니다. OOP 모델에 익숙한 프로그래머는 프로그래밍이 R로 직접 전송되지 않는다는 사실에 실망하거나 혼란 스러울 때가 있지만 그렇게 할 수는 없습니다. 메서드의 기능적 사용은 더 복잡하지만 의미있는 기능을 갖도록 조정되어 OOP 버전으로 축소 할 수 없습니다.


14

S3 및 S4는 OO 프로그래밍을위한 공식 (즉, 내장) 접근 방식 인 것 같습니다. S3와 생성자 함수 / 메서드에 포함 된 함수의 조합을 사용하기 시작했습니다. 내 목표는 object $ method () 유형 구문을 사용하여 반 개인 필드를 갖는 것입니다. 나는 그들을 정말로 숨길 방법이 없기 때문에 (내가 아는 한) 반 비공개라고 말합니다. 다음은 실제로 아무것도하지 않는 간단한 예입니다.

#' Constructor
EmailClass <- function(name, email) {
    nc = list(
        name = name,
        email = email,
        get = function(x) nc[[x]],
        set = function(x, value) nc[[x]] <<- value,
        props = list(),
        history = list(),
        getHistory = function() return(nc$history),
        getNumMessagesSent = function() return(length(nc$history))
    )
    #Add a few more methods
    nc$sendMail = function(to) {
        cat(paste("Sending mail to", to, 'from', nc$email))
        h <- nc$history
        h[[(length(h)+1)]] <- list(to=to, timestamp=Sys.time())
        assign('history', h, envir=nc)
    }
    nc$addProp = function(name, value) {
        p <- nc$props
        p[[name]] <- value
        assign('props', p, envir=nc)
    }
    nc <- list2env(nc)
    class(nc) <- "EmailClass"
    return(nc)
}

#' Define S3 generic method for the print function.
print.EmailClass <- function(x) {
    if(class(x) != "EmailClass") stop();
    cat(paste(x$get("name"), "'s email address is ", x$get("email"), sep=''))
}

그리고 일부 테스트 코드 :

    test <- EmailClass(name="Jason", "jason@bryer.org")
    test$addProp('hello', 'world')
    test$props
    test
    class(test)
    str(test)
    test$get("name")
    test$get("email")
    test$set("name", "Heather")
    test$get("name")
    test
    test$sendMail("jbryer@excelsior.edu")
    test$getHistory()
    test$sendMail("test@domain.edu")
    test$getNumMessagesSent()

    test2 <- EmailClass("Nobody", "dontemailme@nowhere.com")
    test2
    test2$props
    test2$getHistory()
    test2$sendMail('nobody@exclesior.edu')

다음은이 접근 방식에 대해 작성한 블로그 게시물에 대한 링크입니다. http://bryer.org/2012/object-oriented-programming-in-r 이 접근 방식 에 대한 의견, 비판 및 제안을 환영합니다. 이것이 최선의 방법이라면 나 자신. 그러나 내가 해결하려고 노력한 문제는 훌륭하게 작동했습니다. 특히 makeR 패키지 ( http://jbryer.github.com/makeR )의 경우 내 개체의 상태를 나타내는 XML 파일이 동기화 상태를 유지해야했기 때문에 사용자가 데이터 필드를 직접 변경하는 것을 원하지 않았습니다. 사용자가 문서에 설명 된 규칙을 준수하는 한 완벽하게 작동했습니다.


10
당신은 위의 코드를 사용하여 "손으로"참조 클래스를 재창조하고 있습니다. 그것은 단지 일을 훨씬 더 취약하게 만듭니다.
Simon Urbanek 2012 년

감사합니다 Simon. 나는 이것을 게시하기 전까지 ReferenceClasses를 알지 못했습니다.
jbryer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.