Menu
CoddyTech

Tạo Generics

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 27 trên 57.

Bạn tạo generic S4 bằng setGeneric(). Phần thân hàm của nó là standardGeneric("name"), phiên bản tương đương trong S4 của UseMethod(). setGeneric() trả về tên của generic, tên này sẽ được in ra khi bạn gọi hàm ở cấp cao nhất:

setGeneric("area", function(shape) standardGeneric("area"))

Đầu ra:

[1] "area"

Bọc lời gọi trong invisible() để ẩn dòng đó khỏi đầu ra. Tiếp theo, setMethod("area", "Circle", ...) thêm phương thức cho một lớp:

setClass("Circle", slots = c(r = "numeric"))
setClass("Square", slots = c(side = "numeric"))
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
setMethod("area", "Square", function(shape) shape@side^2)
cat(area(new("Circle", r = 1)), area(new("Square", side = 3)))

Đầu ra:

3.141593 9

Phương thức có cùng các đối số với hàm generic. Khi hàm generic có ..., phương thức có thể thêm các đối số có tên riêng sau đó:

setClass("Circle", slots = c(r = "numeric"))
invisible(setGeneric("describe", function(x, ...) standardGeneric("describe")))
setMethod("describe", "Circle", function(x, ..., digits = 2) {
  paste("circle of area", round(pi * x@r^2, digits))
})
c1 <- new("Circle", r = 2)
print(describe(c1))
print(describe(c1, digits = 4))

Đầu ra:

[1] "circle of area 12.57"
[1] "circle of area 12.5664"

setMethod() cần generic đã tồn tại, vì vậy tệp có setGeneric() được nạp trước. Lệnh gọi cho một lớp không có phương thức sẽ dừng và báo lỗi nêu rõ chữ ký:

invisible(setGeneric("area", function(shape) standardGeneric("area")))
setClass("Circle", slots = c(r = "numeric"))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
area(42)

Đầu ra:

Error: unable to find an inherited method for function ‘area’ for signature ‘shape = "numeric"’
Execution halted
challenge icon

Thử thách

Dễ

Các hình là lớp S4 trong ba tệp. Trong Shape.R, hãy tạo các hàm tổng quát area(shape) và perimeter(shape) bằng setGeneric(), bọc chúng trong invisible(). Trong Circle.R và Square.R, các lớp đã được khai báo; hãy thêm các phương thức area và perimeter cho từng lớp bằng setMethod().

Code được cung cấp đọc các dòng circle 2 hoặc square 3 và in ra circle: area 12.57, perimeter 12.57.

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

Tự làm thử

source("Shape.R")
source("Circle.R")
source("Square.R")

# Đoạn code đầu vào/đầu ra đã cho: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  s <- if (p[1] == "circle") new("Circle", r = as.numeric(p[2])) else new("Square", side = as.numeric(p[2]))
  cat(sprintf("%s: area %.2f, perimeter %.2f", p[1], area(s), perimeter(s)), "\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