팩토리 메서드
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: orangeprivate_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챌린지
쉬움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) }}"
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 Ruby 컴파일러