Menu
Coddy logo textTech

nextMethod()로 확장하기

Coddy R 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 14번째.

자식 메서드는 부모의 작업에 약간의 작업을 더하는 경우가 많습니다. NextMethod()는 부모 메서드를 호출하므로, 자식은 새로 추가된 부분만 구현하면 됩니다. 관리자의 월급은 직원의 월급에 보너스를 더한 금액입니다:

pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
pay.manager <- function(x) NextMethod() + x$bonus / 12
m <- structure(list(salary = 60000, bonus = 12000), class = c("manager", "employee"))
e <- structure(list(salary = 36000), class = "employee")
cat(pay(e), pay(m))

출력:

3000 6000

NextMethod()는 여러 수준에 걸쳐 계속 작동합니다. 각 메서드는 자신의 부분을 추가하고, 자신 다음의 클래스에 처리를 넘깁니다:

pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
pay.manager <- function(x) NextMethod() + x$bonus / 12
pay.director <- function(x) NextMethod() + 500
d <- structure(list(salary = 120000, bonus = 24000),
               class = c("director", "manager", "employee"))
print(pay(d))

출력:

[1] 12500

자식 메서드는 먼저 확인한 후, 확인이 통과된 경우에만 처리를 부모 메서드에 넘길 수도 있습니다. 부모 메서드는 전체 클래스 벡터를 포함하여 변경된 객체를 반환하므로, 결과는 여전히 저축 계좌입니다:

withdraw <- function(acc, amount) UseMethod("withdraw")
withdraw.account <- function(acc, amount) {
  if (amount > acc$balance) stop("insufficient funds", call. = FALSE)
  acc$balance <- acc$balance - amount
  acc
}
withdraw.savings <- function(acc, amount) {
  if (amount > 500) stop("savings limit is 500", call. = FALSE)
  NextMethod()
}
s <- structure(list(balance = 1000), class = c("savings", "account"))
s <- withdraw(s, 200)
cat(s$balance, class(s))

출력:

800 savings account

생성자와 메서드는 동일한 방식으로 부모를 재사용합니다. new_manager()는 new_employee()를 호출하고, pay.manager()는 NextMethod()를 호출합니다. 직원 코드는 한 번만 작성하며 모든 하위 클래스가 이를 기반으로 구축됩니다:

new_manager <- function(name, salary, bonus) {
  new_employee(name, salary, bonus = bonus, class = "manager")   # 생성자를 재사용
}
pay.manager <- function(x) NextMethod() + x$bonus / 12            # 메서드를 재사용
challenge icon

챌린지

쉬움

계정과 저축 계정은 두 파일에 있습니다. Account.R에서 금액이 잔액보다 클 때 insufficient funds와 함께 중단하고, 그렇지 않으면 잔액이 줄어든 계정을 반환하는 withdraw.account(acc, amount)와 ada: 800을 반환하는 format.account()을 완성하세요. Savings.R에서는 금액이 500보다 클 때 savings limit is 500과 함께 중단하고, 그렇지 않으면 NextMethod()로 처리를 넘기는 withdraw.savings()와 NextMethod()을 호출하여 ada: 800 (savings)을 반환하는 format.savings()을 완성하세요.

call. = FALSE를 사용하세요. 제네릭과 생성자는 제공되어 있습니다. 제공된 코드는 savings ada 1000 또는 account bo 300을 읽은 다음 인출할 금액을 읽습니다. withdrew 200 또는 refused: 와 메시지를 출력하고, 마지막으로 형식이 지정된 계정을 출력합니다.

코드는 Account.R과 Savings.R에 작성하세요. main.R에는 제공된 입력/출력 코드가 들어 있으며 수정할 수 없습니다.

직접 해보기

source("Account.R")
source("Savings.R")

# 제공된 입력/출력 코드: 그대로 유지하세요
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], " ")[[1]]
acc <- if (p[1] == "savings") new_savings(p[2], as.numeric(p[3])) else new_account(p[2], as.numeric(p[3]))
for (amount in as.numeric(input[-1])) {
  acc <- tryCatch({
    acc <- withdraw(acc, amount)
    cat("withdrew ", amount, "\n", sep = "")
    acc
  }, error = function(e) {
    cat("refused: ", conditionMessage(e), "\n", sep = "")
    acc
  })
}
cat(format(acc), "\n", sep = "")
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 R 컴파일러