Menu
CoddyTech

Fungsi Konstruktor

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan R di Coddy. Pelajaran 3 dari 57.

Karena R tidak pernah memeriksa field object S3, setiap object dari suatu class harus dibuat oleh satu fungsi, yaitu constructor-nya. Sesuai konvensi, constructor tingkat rendah diberi nama new_ ditambah nama class. Constructor ini menerima setiap field sebagai argumen, memeriksa tipe dengan stopifnot(), lalu mengembalikan object:

new_money <- function(amount = double(), currency = character()) {
  stopifnot(is.double(amount), is.character(currency))
  structure(list(amount = amount, currency = currency), class = "money")
}
m <- new_money(9.5, "EUR")
cat(m$amount, m$currency)

Output:

9.5 EUR

stopifnot() menghentikan program ketika salah satu kondisinya tidak TRUE, dan pesannya menyebutkan pemeriksaan yang gagal. Tipe yang salah terdeteksi saat object dibuat, bukan nanti ketika fungsi lain menggunakannya:

new_money <- function(amount = double(), currency = character()) {
  stopifnot(is.double(amount), is.character(currency))
  structure(list(amount = amount, currency = currency), class = "money")
}
m <- new_money("9.5", "EUR")

Output:

Error in new_money("9.5", "EUR") : is.double(amount) is not TRUE
Calls: new_money -> stopifnot
Execution halted

Konstruktor adalah satu-satunya tempat yang memanggil structure() untuk class tersebut, sehingga setiap object memiliki field yang sama dalam urutan yang sama. Kode yang membutuhkan banyak object memanggilnya dalam perulangan atau dengan lapply():

new_point <- function(x = 0, y = 0) {
  stopifnot(is.numeric(x), is.numeric(y))
  structure(list(x = x, y = y), class = "point")
}
pts <- lapply(1:3, function(i) new_point(i, i * i))
for (p in pts) cat(p$x, p$y, "\n")

Output:

1 1 
2 4 
3 9 

object S3 tidak harus berupa list. Constructor dapat memberi label pada vektor biasa dan menyimpan fakta tambahan sebagai atribut, seperti cara kerja factor dan tanggal bawaan R. attr(x, "unit") membaca atribut:

new_distance <- function(value = double(), unit = "m") {
  stopifnot(is.double(value), is.character(unit))
  structure(value, unit = unit, class = "distance")
}
d <- new_distance(c(1.5, 2), "km")
print(attr(d, "unit"))
print(unclass(d)[2] * 1000)

Output:

[1] "km"
[1] 2000
challenge icon

Tantangan

Mudah

Lengkapi constructor new_book(title, author, pages) di Book.R. Constructor ini memeriksa dengan stopifnot() bahwa title dan author bertipe character, sedangkan pages bertipe numeric, lalu mengembalikan list dengan ketiga field tersebut dan class book. Lalu lengkapi book_label(b), yang mengembalikan Dune by Frank Herbert, 412 pages.

Kode yang disediakan membaca baris dengan format title;author;pages. Kode tersebut meneruskan pages sebagai angka jika nilainya terdiri dari digit, dan sebagai teks asli jika tidak, mencetak book: dan label untuk setiap object, serta mencetak rejected: dan judulnya ketika constructor berhenti.

Tuliskan kodemu di Book.R. main.R berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

source("Book.R")

# Kode input/output yang disediakan: biarkan apa adanya
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, ";")[[1]]
  pages <- if (grepl("^[0-9]+$", p[3])) as.numeric(p[3]) else p[3]
  b <- tryCatch(new_book(p[1], p[2], pages), error = function(e) NULL)
  if (is.null(b)) {
    cat("rejected: ", p[1], "\n", sep = "")
  } else {
    cat(class(b), ": ", book_label(b), "\n", sep = "")
  }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler R online