Menu
Coddy logo textTech

메서드와 필드 업데이트

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

메서드는 setRefClass()의 methods 목록에 넣습니다. 메서드 안에서 필드는 일반적인 이름으로 사용되며, <<-는 필드를 변경합니다. Coddy 러너에서는 메서드가 있는 클래스를 정의할 때 선택 사항인 codetools 패키지에 대한 안내 메시지를 R이 출력하므로, 정의를 suppressMessages()로 감싸세요:

Counter <- suppressMessages(setRefClass("Counter",
  fields = list(count = "numeric"),
  methods = list(
    add = function(n = 1) {
      count <<- count + n
    },
    report = function() paste("count is", count)
  )
))
c1 <- Counter$new(count = 0)
c1$add()
c1$add(5)
print(c1$report())

출력:

[1] "count is 6"

.self는 메서드가 호출된 객체입니다. invisible(.self)로 끝나는 메서드는 객체를 반환하므로 호출을 연쇄적으로 연결할 수 있습니다:

Counter <- suppressMessages(setRefClass("Counter",
  fields = list(count = "numeric"),
  methods = list(
    add = function(n = 1) {
      count <<- count + n
      invisible(.self)
    }
  )
))
c1 <- Counter$new(count = 0)
c1$add(2)$add(3)$add(4)
print(c1$count)

출력:

[1] 9

initialize 메서드는 $new() 내부에서 실행됩니다. initFields(...)는 전달된 필드를 설정하며, 이후 메서드는 나머지 필드에 기본값을 지정할 수 있습니다. 메서드는 이름으로 서로 호출합니다:

Account <- suppressMessages(setRefClass("Account",
  fields = list(owner = "character", balance = "numeric"),
  methods = list(
    initialize = function(...) {
      initFields(...)
      if (length(balance) == 0) balance <<- 0
      invisible(.self)
    },
    deposit = function(x) balance <<- balance + x,
    deposit_twice = function(x) {
      deposit(x)
      deposit(x)
    }
  )
))
a <- Account$new(owner = "Ada")
a$deposit_twice(10)
print(a$balance)

출력:

[1] 20

메서드 내부에서 필드 이름에 일반적인 <-를 사용하면 해당 이름의 지역 변수가 생성되고 필드는 변경되지 않습니다. 필드를 변경할 때마다 <<-를 사용하세요:

Counter <- suppressMessages(setRefClass("Counter",
  fields = list(count = "numeric"),
  methods = list(
    broken = function() count <- count + 1,
    working = function() count <<- count + 1
  )
))
c1 <- Counter$new(count = 0)
c1$broken()
c1$broken()
c1$working()
print(c1$count)

출력:

[1] 1
challenge icon

챌린지

쉬움

Stack 참조 클래스를 Stack.R에서 완성하세요. 이 클래스는 필드 items에 항목을 저장하며(문자형이고, 마지막 항목이 가장 위에 있음) 네 가지 메서드를 가집니다:

  • push(x)는 x를 맨 위에 추가하고 invisible(.self)를 반환하므로, 여러 push를 연결할 수 있습니다;
  • pop()은 맨 위 항목을 제거하고 반환하며, 스택이 비어 있으면 nothing을 반환합니다;
  • peek()은 맨 위 항목을 제거하지 않고 반환하며, 비어 있으면 nothing을 반환합니다;
  • size()는 항목의 개수를 반환합니다.

정의는 이미 suppressMessages()로 감싸져 있습니다. 제공된 코드는 push a b, pop, peek 명령을 읽은 다음, 연결된 호출 하나로 항목을 두 개 더 추가하고 크기를 출력합니다.

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

직접 해보기

source("Stack.R")

# 제공된 입력/출력 코드: 그대로 유지하세요
input <- suppressWarnings(readLines(file("stdin")))
s <- Stack$new()
for (cmd in input) {
  if (startsWith(cmd, "push ")) {
    items <- strsplit(substring(cmd, 6), " ")[[1]]
    for (it in items) s$push(it)
  } else if (cmd == "pop") {
    cat("popped ", s$pop(), "\n", sep = "")
  } else if (cmd == "peek") {
    cat("top ", s$peek(), "\n", sep = "")
  }
}
s$push("x")$push("y")
cat("size after two chained pushes: ", s$size(), "\n", sep = "")
quiz icon실력 점검

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

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

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