Menu
CoddyTech

Điều phối theo hai đối số

Thuộc phần Lập trình hướng đối tượng trong hành trình R của Coddy. Bài học 29 trên 57.

Generic S4 có thể chọn phương thức dựa trên lớp của nhiều đối số. Chữ ký liệt kê một lớp cho mỗi đối số, vì vậy mỗi cặp lớp có thể có phương thức riêng:

setClass("Asteroid", slots = c(size = "numeric"))
setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Asteroid", "Ship"), function(a, b) paste(b@name, "is hit"))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
rock <- new("Asteroid", size = 3)
enterprise <- new("Ship", name = "Enterprise")
print(collide(rock, enterprise))
print(collide(enterprise, enterprise))

Đầu ra:

[1] "Enterprise is hit"
[1] "two ships bump"

Lớp "ANY" khớp với mọi lớp. Phương thức cho signature("ANY", "ANY") là phương án dự phòng, chạy khi không có cặp cụ thể hơn nào phù hợp:

setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
setMethod("collide", signature("ANY", "ANY"), function(a, b) "nothing happens")
s <- new("Ship", name = "A")
cat(collide(s, s), "/", collide(s, 42), "/", collide("x", "y"))

Đầu ra:

two ships bump / nothing happens / nothing happens

Thứ tự của các đối số rất quan trọng: signature("A", "B") và signature("B", "A") là các phương thức khác nhau. Các lớp cơ bản như numeric và character cũng có thể xuất hiện trong chữ ký:

invisible(setGeneric("join", function(x, y) standardGeneric("join")))
setMethod("join", signature("character", "numeric"), function(x, y) paste(x, "number", y))
setMethod("join", signature("numeric", "character"), function(x, y) paste(y, "after number", x))
print(join("item", 3))
print(join(3, "item"))

Đầu ra:

[1] "item number 3"
[1] "item after number 3"

Lớp "missing" trong chữ ký khớp với một đối số hoàn toàn không được cung cấp, vì vậy một hàm generic có thể hỗ trợ cả dạng ngắn và dạng dài:

invisible(setGeneric("greet", function(name, greeting) standardGeneric("greet")))
setMethod("greet", signature("character", "missing"), function(name, greeting) paste("Hello,", name))
setMethod("greet", signature("character", "character"), function(name, greeting) paste0(greeting, ", ", name))
print(greet("Ada"))
print(greet("Ada", "Good morning"))

Đầu ra:

[1] "Hello, Ada"
[1] "Good morning, Ada"
challenge icon

Thử thách

Dễ

Giá vận chuyển phụ thuộc vào món hàng và khu vực. Các lớp được khai báo trong Item.R (Letter, Box, mỗi lớp có một slot kg) và Zone.R (Domestic, Abroad, mỗi lớp có một slot name). Trong Rates.R, hãy tạo hàm tổng quát shipping(item, zone) và một phương thức cho mỗi cặp:

  • Letter trong nước: 1; nước ngoài: 3.
  • Box trong nước: 5 cộng 2 cho mỗi kg; nước ngoài: 12 cộng 4 cho mỗi kg.
  • Mọi cặp khác: dừng lại với no rate for this item and zone (dùng call. = FALSE).

Code được cung cấp đọc các dòng box home 2.5 (món hàng, khu vực, kg), trong đó các từ không xác định vẫn là văn bản thông thường, rồi in ra box to home: 10.00 hoặc error: cùng thông báo lỗi.

Code của bạn nằm trong Item.R, Zone.R và Rates.R. main.R chứa code đầu vào/đầu ra được cung cấp và không thể chỉnh sửa.

Tự làm thử

source("Item.R")
source("Zone.R")
source("Rates.R")

# Đoạn code đầu vào/đầu ra đã có sẵn: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  kg <- as.numeric(p[3])
  item <- switch(p[1], letter = new("Letter", kg = kg), box = new("Box", kg = kg), kg)
  zone <- switch(p[2], home = new("Domestic", name = "home"), abroad = new("Abroad", name = "abroad"), p[2])
  out <- tryCatch(sprintf("%s to %s: %.2f", p[1], p[2], shipping(item, zone)),
                  error = function(e) paste("error:", conditionMessage(e)))
  cat(out, "\n", sep = "")
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch R online