두 인수에 대한 디스패치
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"챌린지
쉬움배송 가격은 항목과 구역에 따라 달라집니다. 클래스는 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 = "")
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 R 컴파일러