Menu
CoddyTech

Thứ tự tra cứu phương thức

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

Với mỗi lần gọi, R duyệt qua vector lớp từ trái sang phải và chạy phương thức đầu tiên tìm thấy. Nếu không lớp nào có phương thức đó, R sẽ dùng phương thức mặc định. Các đối tượng khác nhau trong cùng một hệ phân cấp có thể dừng ở các cấp độ khác nhau:

move <- function(x) UseMethod("move")
move.animal <- function(x) "walks"
move.bird <- function(x) "flies"
move.default <- function(x) "stays"
penguin <- structure(list(), class = c("penguin", "bird", "animal"))
dog <- structure(list(), class = c("dog", "animal"))
rock <- structure(list(), class = "rock")
cat(move(penguin), move(dog), move(rock))

Đầu ra:

flies walks stays

Lớp con ghi đè phương thức của lớp cha bằng cách định nghĩa phương thức riêng. Việc ghi đè chỉ ảnh hưởng đến lớp con và mọi lớp bên dưới nó; lớp cha và các lớp con khác vẫn giữ phương thức của lớp cha:

move <- function(x) UseMethod("move")
move.animal <- function(x) "walks"
move.bird <- function(x) "flies"
move.penguin <- function(x) "swims"
penguin <- structure(list(), class = c("penguin", "bird", "animal"))
sparrow <- structure(list(), class = c("bird", "animal"))
cat(move(penguin), move(sparrow))

Đầu ra:

swims flies

Mỗi hàm generic được tra cứu riêng. Một đối tượng có thể lấy sound() từ lớp của chính nó và move() từ lớp cha, còn một phương thức của lớp cha có thể gọi các hàm generic khác để chúng lại phân phối theo lớp con:

sound <- function(x) UseMethod("sound")
move <- function(x) UseMethod("move")
describe <- function(x) UseMethod("describe")
sound.animal <- function(x) "..."
sound.dog <- function(x) "woof"
move.animal <- function(x) "walks"
describe.animal <- function(x) paste(x$name, "says", sound(x), "and", move(x))
rex <- structure(list(name = "Rex"), class = c("dog", "animal"))
print(describe(rex))

Đầu ra:

[1] "Rex says woof and walks"

Với một đối tượng có thuộc tính lớp, cơ chế điều phối chỉ xét thuộc tính đó rồi đến phương thức mặc định. Bên trong, đối tượng vẫn là một danh sách, nhưng phương thức dành cho list không được thử:

size <- function(x) UseMethod("size")
size.list <- function(x) "a list"
size.default <- function(x) "default"
bag <- structure(list(1, 2), class = "bag")
cat(size(list(1, 2)), "/", size(bag))

Đầu ra:

a list / default
challenge icon

Thử thách

Dễ

Hình vuông là hình chữ nhật có các cạnh bằng nhau. Trong Rectangle.R, hãy viết các phương thức area.rectangle(), perimeter.rectangle() và name.rectangle(), trả về rectangle 2x3. Trong Square.R, hãy hoàn thiện new_square(side), hàm này gọi new_rectangle() với lớp square, và chỉ ghi đè name() bằng name.square(), trả về square 2. Hình vuông phải dùng area() và perimeter() của hình chữ nhật.

Các hàm generic và new_rectangle() đã được cung cấp. Code có sẵn đọc các dòng gồm hai số (hình chữ nhật) hoặc một số (hình vuông) rồi in ra square 2: area 4, perimeter 8.

Code của bạn đặt trong Rectangle.R và Square.R. main.R chứa code đầu vào/đầu ra đã cung cấp và bạn không thể chỉnh sửa.

Tự làm thử

source("Rectangle.R")
source("Square.R")

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  n <- as.numeric(strsplit(line, " ")[[1]])
  s <- if (length(n) == 1) new_square(n[1]) else new_rectangle(n[1], n[2])
  cat(name(s), ": area ", area(s), ", perimeter ", 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