Menu
Coddy logo textTech

객체 확장하기

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

extend는 모듈의 메서드를 모든 인스턴스가 아니라 하나의 객체에 추가합니다. 클래스를 확장하면 해당 메서드가 클래스 객체에 추가되므로 클래스 메서드가 됩니다:

module Describable
  def describe
    "#{name} has #{instance_methods(false).size} methods"
  end
end

class Dog
  extend Describable

  def bark
    "Woof"
  end

  def sit
    "sits"
  end
end

puts Dog.describe

출력:

Dog has 2 methods

extend와 함께 사용되는 모듈은 클래스의 인스턴스 변수에 상태를 저장할 수 있습니다. 이를 확장하는 각 클래스는 클래스 인스턴스 변수로서 자신만의 복사본을 갖습니다:

module Counted
  def created
    @created ||= 0
  end

  def record
    @created = created + 1
  end
end

class Order
  extend Counted
end

class Invoice
  extend Counted
end

Order.record
Order.record
Invoice.record
puts "#{Order.created} #{Invoice.created}"

출력:

2 1

extend는 단일 객체에도 작동합니다. 메서드를 얻는 것은 해당 객체뿐이며, 같은 클래스의 다른 인스턴스는 변경되지 않고, 확장된 객체에 대해서만 is_a?가 true입니다:

module Shiny
  def polish
    "#{self} is shining"
  end
end

a = "car"
b = "bike"
a.extend(Shiny)
puts a.polish
puts a.is_a?(Shiny)
puts b.respond_to?(:polish)

출력:

car is shining
true
false

이 두 키워드는 같은 모듈의 메서드를 서로 다른 위치에 배치합니다. include는 클래스의 인스턴스 메서드로 만들고, extend는 확장되는 하나의 객체의 메서드로 만듭니다:

class Order
  include Printable    # order.print_me       (모든 인스턴스)
  extend Counted       # Order.record         (클래스 자체)
end

item.extend(Shiny)     # item.polish          (이 객체만)
challenge icon

챌린지

쉬움

extend와 함께 사용하는 Registry 모듈을 완성하세요. register(name)은 클래스 자체의 목록에 이름을 추가하며, 이 목록은 @entries에 저장됩니다(처음 사용될 때 생성됨). 그리고 Plugin registered x를 반환합니다. 이미 목록에 있는 이름이면 Plugin already has x를 반환합니다. entries는 목록을 반환하고, count는 목록의 크기를 반환합니다. Plugin과 Theme은 모두 Registry를 확장하며 서로 별도의 목록을 유지합니다.

제공된 코드는 plugin name 또는 theme name 형식의 줄을 읽고, 일치하는 클래스에서 register를 호출한 다음 응답을 출력합니다. 마지막으로 plugins: a, b (2)와 themes: ...를 출력하며, 목록이 비어 있으면 none (0)을 출력합니다.

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

직접 해보기

require_relative 'registry'
require_relative 'plugin'
require_relative 'theme'

# 제공된 입력/출력 코드: 있는 그대로 유지하세요
input = []
while (line = gets)
  input << line.chomp
end
input.each do |line|
  kind, name = line.split
  target = kind == "plugin" ? Plugin : Theme
  puts target.register(name)
end
[["plugins", Plugin], ["themes", Theme]].each do |label, klass|
  list = klass.entries.empty? ? "none" : klass.entries.join(", ")
  puts "#{label}: #{list} (#{klass.count})"
end
quiz icon실력 점검

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

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

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