Menu
Coddy logo textTech

다형성

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

다형성은 하나의 메서드 호출이 서로 다른 클래스의 객체에서 작동하고, 각 객체가 자신만의 방식으로 응답하는 것을 의미합니다. 도형을 순회하는 코드는 각 도형의 종류를 묻지 않고 각각에 대해 area를 호출합니다:

class Shape
  def to_s
    format("%s %.2f", self.class.name.downcase, area)
  end
end

class Circle < Shape
  def initialize(r)
    @r = r
  end

  def area
    3.14159 * @r * @r
  end
end

class Square < Shape
  def initialize(side)
    @side = side
  end

  def area
    @side * @side
  end
end

shapes = [Circle.new(1), Square.new(3)]
shapes.each { |s| puts s }
puts format("total %.2f", shapes.sum(&:area))

출력:

circle 3.14
square 9.00
total 12.14

다형성이 없다면 호출자는 모든 객체의 종류를 확인하고, 그 차이가 중요한 곳마다 같은 확인을 반복해야 합니다. 다형성을 사용하면 그 차이는 각 클래스 내부에 존재합니다:

# 다형성 없이
case shape.kind
when "circle" then 3.14159 * shape.r ** 2
when "square" then shape.side ** 2
end

# 다형성으로
shape.area

새로운 종류의 객체를 추가해도 호출 코드를 변경할 필요가 없습니다. 자체 area를 가진 새로운 서브클래스는 이미 존재하는 모든 루프에서 작동합니다:

class Shape
  def describe
    "area #{area}"
  end
end

class Square < Shape
  def area
    4
  end
end

class Triangle < Shape
  def area
    6
  end
end

[Square.new, Triangle.new].each { |s| puts s.describe }

출력:

area 4
area 6

to_s는 일상적인 예입니다. puts는 모든 객체에 대해 이를 호출하며, 각 클래스는 서로 다르게 응답합니다. 여러분의 클래스도 자체 to_s를 정의하여 이에 참여할 수 있습니다.

class Coin
  def to_s
    "a coin"
  end
end

[42, "text", nil, [1, 2], Coin.new].each { |x| puts "[#{x}]" }

출력:

[42]
[text]
[]
[[1, 2]]
[a coin]
challenge icon

챌린지

쉬움

도형을 완성하세요. Shape#to_s는 소문자로 된 클래스 이름과 소수점 이하 두 자리로 표시된 넓이를 사용하여 circle: 3.14를 반환하며, 각 하위 클래스는 area를 제공합니다: Circle.new(r)(원주율에는 3.14159 사용), Rectangle.new(w, h) 및 Triangle.new(base, height)입니다.

제공된 코드는 circle 1, rectangle 2 3 또는 triangle 4 5 형식의 줄을 읽고, 모든 도형을 출력한 다음 total: 22.14와 largest: rectangle: 6.00을 출력하며, to_s와 area만 사용합니다.

코드는 shape.rb, circle.rb, rectangle.rb 및 triangle.rb에 작성합니다. main.rb에는 제공된 입력/출력 코드가 들어 있으며 편집할 수 없습니다.

직접 해보기

require_relative 'shape'
require_relative 'circle'
require_relative 'rectangle'
require_relative 'triangle'

# 제공된 입력/출력 코드: 그대로 유지하세요
input = []
while (line = gets)
  input << line.chomp
end
kinds = { "circle" => Circle, "rectangle" => Rectangle, "triangle" => Triangle }
shapes = input.map do |line|
  kind, *numbers = line.split
  kinds[kind].new(*numbers.map(&:to_f))
end
shapes.each { |s| puts s }
puts format("total: %.2f", shapes.sum(&:area))
puts "largest: #{shapes.max_by(&:area)}"
quiz icon실력 점검

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

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

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