R và lập trình hướng đối tượng


80

Lập trình hướng đối tượng theo cách này hay cách khác rất khả thi trong R. Tuy nhiên, không giống như Python, có nhiều cách để đạt được hướng đối tượng:

Câu hỏi của tôi là:

Sự khác biệt chính nào phân biệt các cách lập trình OO này trong R?

Lý tưởng nhất là các câu trả lời ở đây sẽ là tài liệu tham khảo cho các lập trình viên R đang cố gắng quyết định phương pháp lập trình OO nào phù hợp nhất với nhu cầu của họ.

Do đó, tôi yêu cầu chi tiết, được trình bày một cách khách quan, dựa trên kinh nghiệm và được hỗ trợ bởi các dữ kiện và tài liệu tham khảo. Điểm thưởng cho việc làm rõ cách các phương pháp này liên kết với các thực hành OO tiêu chuẩn.


1
Thông tin về các lớp tham khảo: stackoverflow.com/questions/5137199/…
Ari B. Friedman,

Cảm ơn, bạn có thể đăng lại liên kết như câu trả lời không? Sẽ rất tuyệt nếu bạn có thể bao gồm một bản tóm tắt nhỏ về các lớp Tham chiếu là gì và tại sao chúng được ưu tiên hơn so với các lớp S3 / S4.
Paul Hiemstra

Một chú chim nhỏ thì thầm vào tai tôi rằng một cuốn sách về điều này sẽ được xuất bản bởi John Chambers. Nhưng đừng nói với ai tôi đã nói điều đó ... ;-)
Dirk Eddelbuettel

1
Có thể cùng một con chim nhỏ đó dán một câu trả lời bên dưới với một số thông tin khác về các lớp Refenence;)
Paul Hiemstra

Câu trả lời:


34

Các lớp S3

  • Không thực sự là đối tượng, nhiều hơn là một quy ước đặt tên
  • Dựa trên. cú pháp: Ví dụ: in, printcuộc gọi print.lm print.anova, v.v. Và nếu không tìm thấy,print.default

S4 lớp

Các lớp tham khảo

proto

  • ggplot2 ban đầu được viết bằng proto, nhưng cuối cùng sẽ được viết lại bằng S3.
  • Khái niệm gọn gàng (nguyên mẫu, không phải lớp), nhưng có vẻ phức tạp trong thực tế
  • Phiên bản tiếp theo của ggplot2 dường như sẽ rời xa nó
  • Mô tả khái niệm và cách thực hiện

Các lớp R6

  • Tham khảo
  • Không phụ thuộc vào các lớp S4
  • " Tạo một lớp R6 tương tự như lớp tham chiếu, ngoại trừ việc không cần phải tách các trường và phương thức, và bạn không thể chỉ định kiểu của các trường."

1
Cảm thấy tự do để chỉnh sửa nếu bạn có sự khác biệt khác để thêm vào Tôi sẽ không khóc nếu nó trở nên CW :-).
Ari B. Friedman

3
đừng quênlibrary("fortunes"); fortune("strait")
Ben Bolker

1
Một cuộc thảo luận về các lớp S4 tại đây: stackoverflow.com/questions/3602154/… . Cảm giác chung dường như là họ gặp nhiều rắc rối hơn thì họ mang lại lợi thế.
Paul Hiemstra

Điều thú vị là các lớp R6 mới ngầm thừa nhận rằng các Lớp Tham chiếu là R5 bằng cách tránh sử dụng số đó. Hãy để cuộc tranh cãi bắt đầu (một lần nữa).
Ari B. Friedman,

1
Cái tên R5 ban đầu được sử dụng như một trò đùa bởi những người không phải là nhà phát triển Lớp tham chiếu. Tên R6 là sự thừa nhận của "R5", nhưng nó không có nghĩa là tên R5 có bất kỳ sự chứng thực chính thức nào.
wch

19

Chỉnh sửa vào ngày 3/8/12: Câu trả lời bên dưới phản hồi một phần của câu hỏi đã đăng ban đầu, sau đó đã bị xóa. Tôi đã sao chép nó bên dưới, để cung cấp ngữ cảnh cho câu trả lời của tôi:

Làm thế nào để các phương thức OO khác nhau ánh xạ tới các phương thức OO tiêu chuẩn hơn được sử dụng trong Java hoặc Python?


Đóng góp của tôi liên quan đến câu hỏi thứ hai của bạn, về cách các phương pháp OO của R ánh xạ với các phương pháp OO tiêu chuẩn hơn. Như tôi đã từng nghĩ về điều này trong quá khứ, tôi đã quay đi quay lại hai đoạn văn, một của Friedrich Leisch, và một của John Chambers. Cả hai đều làm rất tốt trong việc giải thích lý do tại sao lập trình giống OO trong R lại có hương vị khác với nhiều ngôn ngữ khác.

Đầu tiên, Friedrich Leisch, từ "Tạo gói R: Hướng dẫn" ( cảnh báo: PDF ):

S rất hiếm vì nó vừa tương tác vừa có hệ thống hướng đối tượng. Thiết kế các lớp rõ ràng là lập trình, nhưng để làm cho S trở nên hữu ích như một môi trường phân tích dữ liệu tương tác, thì nó là một ngôn ngữ chức năng. Trong các ngôn ngữ lập trình hướng đối tượng (OOP) "thực" như C ++ hoặc Java, các định nghĩa về lớp và phương thức được liên kết chặt chẽ với nhau, các phương thức là một phần của các lớp (và do đó là các đối tượng). Chúng tôi muốn bổ sung gia tăng và tương tác như các phương thức do người dùng xác định cho các lớp được xác định trước. Những bổ sung này có thể được thực hiện bất kỳ lúc nào, ngay cả khi đang di chuyển tại dấu nhắc dòng lệnh trong khi chúng tôi phân tích tập dữ liệu. S cố gắng tạo ra sự thỏa hiệp giữa hướng đối tượng và việc sử dụng tương tác, và mặc dù các thỏa hiệp không bao giờ là tối ưu đối với tất cả các mục tiêu mà họ cố gắng đạt được, chúng thường hoạt động hiệu quả một cách đáng ngạc nhiên trong thực tế.

Đoạn văn khác đến từ cuốn sách tuyệt vời "Phần mềm phân tích dữ liệu" của John Chambers . ( Liên kết đến đoạn trích dẫn ):

Mô hình lập trình OOP khác với ngôn ngữ S ở điểm đầu tiên, mặc dù S và một số ngôn ngữ chức năng khác hỗ trợ các lớp và phương thức. Định nghĩa phương thức trong hệ thống OOP là cục bộ cho lớp; không có yêu cầu rằng cùng một tên cho một phương thức có nghĩa giống nhau đối với một lớp không liên quan. Ngược lại, các định nghĩa phương thức trong R không nằm trong một định nghĩa lớp; về mặt khái niệm, chúng được liên kết với hàm chung. Các định nghĩa lớp tham gia vào việc xác định lựa chọn phương thức, trực tiếp hoặc thông qua kế thừa. Các lập trình viên quen với mô hình OOP đôi khi thất vọng hoặc nhầm lẫn rằng lập trình của họ không chuyển trực tiếp sang R, nhưng nó không thể. Việc sử dụng chức năng của các phương thức phức tạp hơn nhưng cũng cần hài hòa hơn với việc có các chức năng có ý nghĩa và không thể giảm xuống phiên bản OOP.


14

S3 và S4 dường như là các phương pháp tiếp cận chính thức (tức là tích hợp sẵn) cho lập trình OO. Tôi đã bắt đầu sử dụng kết hợp S3 với các hàm được nhúng trong hàm / phương thức của phương thức khởi tạo. Mục tiêu của tôi là có cú pháp kiểu object $ method () để tôi có các trường bán riêng tư. Tôi nói nửa riêng tư bởi vì không có cách nào thực sự che giấu chúng (theo như tôi biết). Đây là một ví dụ đơn giản mà không thực sự làm được gì:

#' 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=''))
}

Và một số mã kiểm tra:

    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')

Đây là liên kết đến một bài đăng trên blog mà tôi đã viết về cách tiếp cận này: http://bryer.org/2012/object-oriented-programming-in-r Tôi hoan nghênh các nhận xét, phê bình và đề xuất cho cách tiếp cận này vì tôi không bị thuyết phục bản thân tôi nếu đây là cách tiếp cận tốt nhất. Tuy nhiên, đối với vấn đề tôi đang cố gắng giải quyết, nó đã hoạt động rất tốt. Cụ thể, đối với gói makeR ( http://jbryer.github.com/makeR ), tôi không muốn người dùng thay đổi trường dữ liệu trực tiếp vì tôi cần đảm bảo rằng tệp XML đại diện cho trạng thái đối tượng của tôi sẽ luôn được đồng bộ hóa. Điều này hoạt động hoàn hảo miễn là người dùng tuân thủ các quy tắc tôi nêu trong tài liệu.


10
Bạn đang phát minh lại các lớp tham chiếu "bằng tay" với đoạn mã trên ... Nó chỉ làm cho mọi thứ trở nên mỏng manh hơn một chút.
Simon Urbanek

Cảm ơn Simon. Tôi không biết về ReferenceClasses cho đến khi tôi đăng bài này.
jbryer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.