Apa arti "metode S3" di R?

125

Karena saya cukup baru mengenal R, saya tidak tahu apa itu metode dan objek S3. Saya menemukan bahwa ada sistem objek S3 dan S4, dan beberapa merekomendasikan untuk menggunakan S3 daripada S4 jika memungkinkan (Lihat Panduan Gaya R Google di http://google-styleguide.googlecode.com/svn/trunk/google-r-style. html ) *. Namun, saya tidak tahu definisi pasti dari metode / objek S3.

Pembaruan: Pada 2019, hyperlink Panduan Gaya R Google sekarang ada di sini .

jiggysoo
sumber

Jawaban:

85

Sebagian besar informasi yang relevan dapat ditemukan dengan melihat ?S3atau ?UseMethod, tetapi secara singkat:

S3 mengacu pada skema pengiriman metode. Jika Anda telah menggunakan R untuk sementara waktu, Anda akan melihat bahwa ada print, predictdan summarymetode untuk banyak jenis objek yang berbeda.

Di S3, ini bekerja dengan:

  • mengatur kelas objek yang menarik (misalnya: nilai kembalian dari panggilan ke metode glmmemiliki kelas glm)
  • menyediakan sebuah metode dengan nama umum (misalnya print), maka titik, dan kemudian classname (misalnya: print.glm)
  • beberapa persiapan harus dilakukan pada nama umum ini ( print) agar ini berfungsi, tetapi jika Anda hanya ingin menyesuaikan diri dengan nama metode yang ada, Anda tidak memerlukan ini (lihat bantuan yang saya rujuk sebelumnya jika Anda melakukannya ).

Untuk mata yang melihatnya, dan khususnya, pengguna paket fitting model funky yang baru Anda buat, jauh lebih nyaman untuk dapat mengetik predict(myfit, type="class")daripada predict.mykindoffit(myfit, type="class").

Ada sedikit lebih banyak dari itu, tetapi ini seharusnya membantu Anda memulai. Ada beberapa kelemahan cara pengiriman metode ini berdasarkan atribut (kelas) objek (dan puritan C mungkin terbangun di malam hari karena ngeri), tetapi untuk banyak situasi, cara ini berfungsi dengan baik. Dengan versi R saat ini, cara-cara baru telah diterapkan (S4 dan kelas referensi), tetapi kebanyakan orang masih (hanya) menggunakan S3.

Nick Sabbe
sumber
55

Untuk membantu Anda memulai S3, lihat kode untuk medianfungsi tersebut. Mengetik medianpada prompt perintah menunjukkan bahwa ia memiliki satu baris dalam tubuhnya, yaitu

UseMethod("median")

Artinya, ini adalah metode S3. Dengan kata lain, Anda dapat memiliki medianfungsi berbeda untuk kelas S3 yang berbeda. Untuk mendaftar semua metode median yang mungkin, ketik

methods(median) #actually not that interesting.  

Dalam kasus ini, hanya ada satu metode, default, yang dipanggil untuk apa saja. Anda dapat melihat kode untuk itu dengan mengetik

median.default

Contoh yang jauh lebih menarik adalah printfungsi, yang memiliki banyak metode berbeda.

methods(print)  #very exciting

Perhatikan bahwa beberapa metode memiliki *s di samping namanya. Itu berarti mereka tersembunyi di dalam beberapa namespace paket. Gunakan finduntuk mengetahui paket mana yang mereka masuki. Misalnya

find("acf")  #it's in the stats package
stats:::print.acf
Richie Cotton
sumber
39

Dari http://adv-r.had.co.nz/OO-essentials.html :

Tiga sistem OO R berbeda dalam cara kelas dan metode didefinisikan:

  • S3 mengimplementasikan gaya pemrograman OO yang disebut OO fungsi-generik. Ini berbeda dari kebanyakan bahasa pemrograman, seperti Java, C ++ dan C #, yang mengimplementasikan OO penyampaian pesan. Dengan penyampaian pesan, pesan (metode) dikirim ke objek dan objek menentukan fungsi yang akan dipanggil. Biasanya, objek ini memiliki tampilan khusus dalam pemanggilan metode, biasanya muncul sebelum nama metode / pesan: misalnya canvas.drawRect ("blue"). S3 berbeda. Sementara komputasi masih dilakukan melalui metode, jenis fungsi khusus yang disebut fungsi generik memutuskan metode mana yang akan dipanggil, misalnya drawRect (kanvas, "biru"). S3 adalah sistem yang sangat kasual. Ini tidak memiliki definisi formal kelas.

  • S4 bekerja mirip dengan S3, tetapi lebih formal. Ada dua perbedaan utama dengan S3. S4 memiliki definisi kelas formal, yang mendeskripsikan representasi dan pewarisan untuk setiap kelas, dan memiliki fungsi pembantu khusus untuk mendefinisikan generik dan metode. S4 juga memiliki beberapa pengiriman, yang berarti bahwa fungsi generik dapat memilih metode berdasarkan kelas dari sejumlah argumen, tidak hanya satu.

  • Kelas referensi, singkatnya disebut RC, sangat berbeda dari S3 dan S4. RC mengimplementasikan OO penyaluran pesan, sehingga metode menjadi milik kelas, bukan fungsi. $ digunakan untuk memisahkan objek dan metode, sehingga pemanggilan metode terlihat seperti canvas $ drawRect ("blue"). Objek RC juga bisa berubah: mereka tidak menggunakan semantik R yang biasa menyalin-saat-memodifikasi, tetapi dimodifikasi pada tempatnya. Hal ini membuat mereka lebih sulit untuk bernalar, tetapi memungkinkan mereka memecahkan masalah yang sulit dipecahkan dengan S3 atau S4.

Ada juga satu sistem lain yang belum sepenuhnya OO, tetapi penting untuk disebutkan di sini:

  • tipe dasar, tipe level-C internal yang mendasari sistem OO lainnya. Jenis dasar sebagian besar dimanipulasi menggunakan kode C, tetapi penting untuk diketahui karena menyediakan blok bangunan untuk sistem OO lainnya.
Amit K Thakur
sumber
12

Saya sampai pada pertanyaan ini kebanyakan bertanya-tanya dari mana nama-nama itu berasal. Tampaknya dari artikel wikipedia ini bahwa nama tersebut mengacu pada versi Bahasa Pemrograman S yang menjadi dasar R. Skema pengiriman metode yang dijelaskan dalam jawaban lain berasal dari S dan diberi label sesuai dengan versi.

Jonathan Adelson
sumber
10

Mencoba

methods(residuals)

yang mencantumkan antara lain "residuals.lm" dan "residuals.glm". Ini berarti ketika Anda telah memasang model linier, m, dan tiperesiduals(m), residuals.lm akan dipanggil. Jika Anda telah memasang model linier umum, residuals.glm akan dipanggil. Ini semacam model objek C ++ yang terbalik. Di C ++, Anda mendefinisikan kelas dasar yang memiliki fungsi virtual, yang diganti dengan kelas turunan. Di R Anda mendefinisikan fungsi virtual (alias generik) dan kemudian Anda memutuskan kelas mana yang akan menggantikan fungsi ini (alias mendefinisikan metode). Perhatikan bahwa kelas yang melakukan ini tidak perlu diturunkan dari satu kelas super umum. Saya tidak setuju untuk lebih memilih S3 daripada S4. S4 memiliki lebih formalisme (= lebih banyak mengetik) dan ini mungkin terlalu banyak untuk beberapa aplikasi. Kelas S4, bagaimanapun, dapat didefinisikan seperti kelas atau struct dalam C ++. Anda dapat menentukan bahwa objek dari kelas tertentu terdiri dari string dan dua angka, misalnya:

setClass("myClass", representation(label = "character", x = "numeric", y = "numeric"))

Metode yang dipanggil dengan objek kelas itu dapat mengandalkan objek yang memiliki anggota tersebut. Itu sangat berbeda dari kelas S3, yang hanya merupakan daftar dari sekumpulan elemen.

Dengan S3 dan S4, Anda memanggil fungsi anggota oleh fun(object, args)dan bukan oleh object$fun(args). Jika Anda mencari sesuatu seperti yang terakhir, lihat paket proto.

Harald Brendel
sumber
Saya cukup yakin bahwa gagasan tentang fungsi anggota dan metode milik objek tidak terlalu masuk akal di R. Metode bukan milik objek (juga fungsi adalah objek juga) tetapi milik fungsi.
petermeissner
3

Berikut adalah ikhtisar cepat yang diperbarui dari berbagai sistem objek R menurut "Advanced R, edisi ke-2" (CRC Press, 2019) oleh Hadley Wickham (Kepala Ilmuwan di RStudio), yang memiliki representasi web di sini , berdasarkan bab tentang Objek Pemrograman Berorientasi .

Sampul buku R tingkat lanjut

Edisi pertama 2015 memiliki representasi web di sini , dengan bab terkait OO di sini .

Pendekatan ke sistem OO

Hadley mendefinisikan berikut ini untuk membedakan dua pendekatan berbeda untuk pemrograman OO:

OOP fungsional : metode (potongan kode yang dapat dipanggil) milik fungsi generik (jangan disamakan dengan metode umum Java / C # ). Pikirkan metode yang terletak di tabel pencarian global. Metode untuk mengeksekusi ditemukan oleh sistem runtime berdasarkan nama fungsi dan jenis (atau kelas objek) dari satu atau lebih argumen yang diteruskan ke fungsi itu (ini disebut "pengiriman metode"). Sintaks-bijaksana, metode panggilan mungkin terlihat seperti fungsi panggilan biasa: myfunc(object, arg1, arg2). Panggilan ini akan mengarahkan runtime untuk mencari metode yang terkait dengan pasangan ("myfunc", typeof (object)) atau mungkin ("myfunc", typeof (object), typeof (arg1), typeof (arg2))jika bahasa mendukung itu. Di R's S3, nama lengkap dari fungsi generik memberikan pasangan (nama-fungsi, kelas) . Sebagai contoh: mean.Dateadalah metode untuk menghitung rata-rata Tanggal. Cobalah methods("mean")untuk membuat daftar metode umum dengan nama fungsi mean. Pendekatan OOP Fungsional ditemukan misalnya di Smalltalk perintis OO , Sistem Objek Lisp Umum dan Julia . Hadley mencatat bahwa "Dibandingkan dengan R, implementasi Julia telah berkembang sepenuhnya dan sangat berkinerja."

OOP terenkapsulasi : metode milik objek atau kelas, dan pemanggilan metode biasanya terlihat seperti object.method(arg1, arg2). Ini disebut enkapsulasi karena objek merangkum data (bidang) dan perilaku (metode). Bayangkan metode ini terletak di tabel pencarian yang dilampirkan ke objek atau deskripsi kelas objek. Runtime mencari metode berdasarkan nama metode dan mungkin jenis dari satu atau beberapa argumen. Ini adalah pendekatan yang ditemukan dalam bahasa OO "populer" seperti C ++, Java, C #.

Dalam kedua kasus tersebut, jika warisan didukung (mungkin memang demikian), runtime dapat melintasi hierarki kelas ke atas hingga menemukan kecocokan untuk kunci pencarian panggilan.

Bagaimana cara mengetahui sistem apa yang dimiliki objek R.

library(sloop) # formerly, "pryr"
otype(mtcars)
#> [1] "S3"

Sistem objek R.

S3

  • Pendekatan OOP fungsional.
  • Sistem terpenting menurut Hadley.
  • Paling sederhana, paling umum. Sistem OO pertama yang digunakan oleh R.
  • Dilengkapi dengan basis R, digunakan di seluruh basis R.
  • Bergantung pada konvensi daripada jaminan yang diberlakukan.
  • Lihat Chambers, John M, dan Trevor J Hastie. 1992. "Model Statistik di S." Wadsworth & Brooks / Cole Advanced Books & Software.
  • Detail ada di "Advanced R, 2nd edition" di sini .

S4

  • Pendekatan OOP fungsional.
  • Sistem terpenting ketiga menurut Hadley.
  • Penulisan ulang S3, oleh karena itu mirip dengan S3, tetapi lebih formal dan lebih ketat: ini memaksa Anda untuk memikirkan dengan hati-hati tentang desain program. Cocok untuk membangun sistem besar (misalnya proyek Biokonduktor ).
  • Diimplementasikan dalam paket "metode" dasar.
  • Lihat: Chambers, John M. 1998. "Programming with Data: A Guide to the S Language." Peloncat.
  • Detail ada di "Advanced R, 2nd edition" di sini .

RC alias "Kelas Referensi"

  • Pendekatan OOP yang dikemas.
  • Dilengkapi dengan basis R.
  • Berdasarkan S4.
  • Objek RC adalah tipe khusus dari objek S4 yang juga "bisa berubah". yaitu, alih-alih menggunakan semantik salin-saat-modifikasi biasa R, semantik ini dapat dimodifikasi di tempat. Perhatikan bahwa status yang bisa berubah sulit untuk dipikirkan dan merupakan sumber bug yang buruk, tetapi dapat menyebabkan kode yang lebih efisien dalam aplikasi tertentu.

R6

  • Pendekatan OOP yang dikemas.
  • Sistem terpenting kedua menurut Hadley.
  • Dapat ditemukan di paket R6 (instal dengan library(R6))
  • Mirip dengan RC, tetapi lebih ringan & lebih cepat: tidak bergantung pada S4 atau paket metode . Dibangun di atas lingkungan R. Juga memiliki:
    • metode publik dan privat
    • ikatan aktif (bidang, yang, saat diakses, sebenarnya memanggil metode)
    • class inhertance yang bekerja di seluruh paket
    • kedua metode kelas (kode yang milik kelas dan dapat mengakses sebuah contoh melalui self, private, super) dan fungsi anggota (fungsi ditugaskan untuk bidang, tetapi yang tidak metode, hanya fungsi)
  • Menyediakan cara standar untuk keluar dari semantik "salin-saat-modifikasi" R
  • Lihat situs paket: "R6: Pemrograman berorientasi objek yang dikemas untuk R" .
  • Detail ada di "Advanced R, 2nd edition" di sini .

Lainnya

Ada yang lain, seperti R.oo (mirip dengan RC), proto (berbasis prototipe, pikirkan JavaScript) dan Mutatr . Namun, "Advanced R" mengatakan:

Selain R6, yang banyak digunakan, sistem ini terutama merupakan kepentingan teoretis. Mereka memang memiliki kelebihan, tetapi hanya sedikit pengguna R yang mengetahui dan memahaminya, jadi sulit bagi orang lain untuk membaca dan berkontribusi pada kode Anda.

Pastikan untuk membaca bab trade-off di "Advanced R, 2nd edition" juga.

David Tonhofer
sumber