Menu
Coddy logo textTech

두 인수에 대한 디스패치

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

S4 제네릭은 여러 인수의 클래스에 따라 메서드를 선택할 수 있습니다. 시그니처에는 각 인수마다 하나의 클래스가 나열되므로, 각 클래스 쌍마다 고유한 메서드를 가질 수 있습니다:

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))

출력:

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

클래스 "ANY"는 모든 클래스와 일치합니다. signature("ANY", "ANY")에 대한 메서드는 더 구체적인 쌍이 일치하지 않을 때 실행되는 대체 메서드입니다:

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"))

출력:

two ships bump / nothing happens / nothing happens

인수의 순서가 중요합니다. signature("A", "B")와 signature("B", "A")는 서로 다른 메서드입니다. numeric 및 character와 같은 기본 클래스도 시그니처에 포함될 수 있습니다.

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"))

출력:

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

시그니처의 "missing" 클래스는 전혀 제공되지 않은 인수와 일치하므로, 하나의 제네릭에서 짧은 형식과 긴 형식을 모두 제공할 수 있습니다:

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"))

출력:

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

챌린지

쉬움

배송 가격은 항목과 구역에 따라 달라집니다. 클래스는 Item.R(Letter, Box, 각각 kg 슬롯 포함)과 Zone.R(Domestic, Abroad, 각각 name 슬롯 포함)에 선언되어 있습니다. Rates.R에서 제네릭 shipping(item, zone)과 각 쌍에 대한 메서드를 하나씩 만드세요:

  • 집에 해당하는 Letter: 1, 해외: 3.
  • 집에 해당하는 Box: 5에 kg당 2를 더함, 해외: 12에 kg당 4를 더함.
  • 그 외의 모든 쌍: no rate for this item and zone과 함께 중지합니다(call. = FALSE 사용).

제공된 코드는 box home 2.5(항목, 구역, kg)과 같은 줄을 읽습니다. 여기서 알 수 없는 단어는 일반 텍스트로 유지되며, box to home: 10.00 또는 error: 와 메시지를 출력합니다.

코드는 Item.R, Zone.R, Rates.R에 작성하세요. main.R에는 제공된 입력/출력 코드가 들어 있으며 편집할 수 없습니다.

직접 해보기

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

# 제공된 입력/출력 코드: 그대로 유지하세요
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 icon실력 점검

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

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

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