Menu
Coddy logo textTech

객체로서의 클로저

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

Logic & Flow에서 클로저를 배웠습니다. 클로저는 다른 함수 안에서 만들어진 함수가 주변의 변수를 유지하는 것입니다. 이러한 함수를 반환하는 함수 팩토리는 객체를 만듭니다. 객체의 지역 변수는 객체의 데이터이고, 함수는 객체의 메서드입니다:

make_account <- function(balance = 0) {
  deposit <- function(x) balance <<- balance + x
  get_balance <- function() balance
  list(deposit = deposit, get_balance = get_balance)
}
acc <- make_account(100)
acc$deposit(50)
print(acc$get_balance())

출력:

[1] 150

팩토리를 호출할 때마다 본문이 다시 실행되므로 각 객체는 자체 변수를 갖습니다. 한 계정을 변경해도 다른 계정에는 영향을 주지 않습니다:

make_account <- function(balance = 0) {
  list(deposit = function(x) balance <<- balance + x,
       get_balance = function() balance)
}
ada <- make_account(100)
bo <- make_account(5)
ada$deposit(1)
cat(ada$get_balance(), bo$get_balance())

출력:

101 5

데이터는 비공개입니다. balance는 목록의 요소가 아니므로 acc$balance는 NULL이며, 여기에 값을 할당해도 관련 없는 요소만 추가됩니다. 목록의 함수들은 객체의 전체 공개 인터페이스입니다:

make_account <- function(balance = 0) {
  list(get_balance = function() balance)
}
acc <- make_account(100)
print(acc$balance)
acc$balance <- 1e6
print(acc$get_balance())

출력:

NULL
[1] 100

메서드는 목록이 만들어지기 전에 지역 함수로 정의되어 있으면 서로 호출할 수 있습니다. 여기서 add_many()는 add()를 재사용합니다:

make_tally <- function() {
  total <- 0
  add <- function(x) total <<- total + x
  add_many <- function(xs) for (x in xs) add(x)
  get <- function() total
  list(add = add, add_many = add_many, get = get)
}
t <- make_tally()
t$add(1)
t$add_many(c(2, 3, 4))
print(t$get())

출력:

[1] 10
challenge icon

챌린지

쉬움

make_counter(start = 0) 팩토리를 Counter.R에서 완성하세요. 이 팩토리는 현재 값을 비공개로 유지하고 네 개의 함수를 포함하는 리스트를 반환합니다. increment()와 decrement()은 값을 1씩 변경하고, reset()은 값을 start로 되돌리며, value()는 값을 반환합니다.

제공된 코드는 시작 값을 읽은 다음 +, - 또는 reset 명령을 읽고 각 명령 후에 값을 출력합니다. 마지막에는 반환된 리스트의 이름을 출력하며, 이 리스트에는 네 함수만 포함되어야 합니다.

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

직접 해보기

source("Counter.R")

# 제공된 입출력 코드: 있는 그대로 유지하세요
input <- suppressWarnings(readLines(file("stdin")))
counter <- make_counter(as.numeric(input[1]))
for (cmd in input[-1]) {
  if (cmd == "+") counter$increment()
  if (cmd == "-") counter$decrement()
  if (cmd == "reset") counter$reset()
  cat(cmd, " -> ", counter$value(), "\n", sep = "")
}
cat("fields visible: ", paste(sort(names(counter)), collapse = ", "), "\n", sep = "")
quiz icon실력 점검

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

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

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