Menu
Coddy logo textTech

팩토리 메서드

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

팩토리 메서드는 인스턴스를 생성하고 반환하는 클래스 메서드입니다. 객체를 만드는 한 가지 방법에 이름을 부여합니다. 클래스 메서드 내부에서 new는 self.new를 의미합니다:

class Temperature
  attr_reader :celsius

  def initialize(celsius)
    @celsius = celsius
  end

  def self.from_fahrenheit(f)
    new((f - 32) * 5 / 9.0)
  end

  def self.freezing
    new(0)
  end
end

puts Temperature.from_fahrenheit(212).celsius
puts Temperature.freezing.celsius

출력:

100.0
0

텍스트를 객체로 변환하는 것은 팩토리가 담당하는 일반적인 작업입니다. 파싱 로직은 클래스 옆에 두고, initialize는 단순하게 유지합니다:

class Duration
  attr_reader :seconds

  def initialize(seconds)
    @seconds = seconds
  end

  def self.parse(text)
    new(text.split(":").map(&:to_i).reduce(0) { |acc, part| acc * 60 + part })
  end
end

puts Duration.parse("1:30").seconds
puts Duration.parse("2:00:05").seconds

출력:

90
7205

팩토리는 잘못된 입력을 거부할 수 있습니다. nil을 반환하면 호출자가 if를 사용해 결과를 테스트할 수 있고, 오류를 발생시키면 호출자가 이를 처리하지 않는 한 프로그램이 중지됩니다:

class Color
  attr_reader :hex

  def initialize(hex)
    @hex = hex
  end

  def self.parse(text)
    return nil unless text.match?(/\A#[0-9a-f]{6}\z/i)

    new(text.downcase)
  end
end

["#FF8800", "orange"].each do |text|
  color = Color.parse(text)
  puts color ? "ok #{color.hex}" : "not a color: #{text}"
end

출력:

ok #ff8800
not a color: orange

private_class_method :new는 new를 클래스 내부에서만 호출할 수 있도록 하므로, 팩토리가 객체를 생성하는 유일한 방법이 됩니다:

class Money
  attr_reader :cents

  def initialize(cents)
    @cents = cents
  end
  private_class_method :new

  def self.from_cents(cents)
    new(cents)
  end
end

puts Money.from_cents(250).cents
begin
  Money.new(250)
rescue NoMethodError => e
  puts e.message
end

출력:

250
private method `new' called for class Money
challenge icon

챌린지

쉬움

Duration 클래스를 완성하세요. initialize(seconds)는 초 단위 숫자를 저장합니다. 팩토리 Duration.parse(text)는 m:ss 또는 h:mm:ss를 읽고, 팩토리 Duration.from_minutes(m)는 정수 분을 받으며, plus(other)는 합계를 담은 새로운 Duration을 반환하고, to_s는 분과 초를 두 자리 숫자로 표시한 h:mm:ss를 반환합니다.

제공된 코드는 시간을 읽습니다. 45m과 같은 줄은 from_minutes를 거치고, 나머지는 parse를 거칩니다. 각 시간을 출력한 다음 마지막으로 total 1:47:10을 출력합니다.

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

직접 해보기

require_relative 'duration'

# 제공된 입력/출력 코드: 그대로 유지하세요
input = []
while (line = gets)
  input << line.chomp
end
durations = input.map do |line|
  line.end_with?("m") ? Duration.from_minutes(line.to_i) : Duration.parse(line)
end
durations.each { |d| puts d }
puts "total #{durations.reduce(Duration.new(0)) { |sum, d| sum.plus(d) }}"
quiz icon실력 점검

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

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

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