객체 확장하기
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 methodsextend와 함께 사용되는 모듈은 클래스의 인스턴스 변수에 상태를 저장할 수 있습니다. 이를 확장하는 각 클래스는 클래스 인스턴스 변수로서 자신만의 복사본을 갖습니다:
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 1extend는 단일 객체에도 작동합니다. 메서드를 얻는 것은 해당 객체뿐이며, 같은 클래스의 다른 인스턴스는 변경되지 않고, 확장된 객체에 대해서만 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 (이 객체만)챌린지
쉬움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
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 Ruby 컴파일러