Polimorfismo
Parte da seção Programação orientada a objetos do Journey de Ruby da Coddy. Lição 32 de 57.
Polimorfismo significa que uma chamada de método funciona em objetos de classes diferentes, e cada objeto responde à sua própria maneira. O código que percorre formas chama area em cada uma delas sem perguntar que tipo de forma ela é:
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))Saída:
circle 3.14
square 9.00
total 12.14Sem polimorfismo, quem chama precisa verificar o tipo de cada objeto e repetir essa verificação onde quer que a diferença seja relevante. Com ele, a diferença fica dentro de cada classe:
# sem polimorfismo
case shape.kind
when "circle" then 3.14159 * shape.r ** 2
when "square" then shape.side ** 2
end
# com polimorfismo
shape.areaAdicionar um novo tipo de objeto não exige nenhuma alteração no código chamador: uma nova subclasse com seu próprio area funciona em todos os loops já existentes:
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 }Saída:
area 4
area 6to_s é o exemplo do dia a dia: puts o chama em qualquer objeto, e cada classe responde de uma forma diferente. Suas classes também participam, definindo seu próprio to_s:
class Coin
def to_s
"a coin"
end
end
[42, "text", nil, [1, 2], Coin.new].each { |x| puts "[#{x}]" }Saída:
[42]
[text]
[]
[[1, 2]]
[a coin]Desafio
FácilComplete as formas. Shape#to_s retorna circle: 3.14, o nome da classe em minúsculas e a área com duas casas decimais, e cada subclasse fornece area: Circle.new(r) (use 3.14159 para pi), Rectangle.new(w, h) e Triangle.new(base, height).
O código fornecido lê linhas circle 1, rectangle 2 3 ou triangle 4 5, imprime cada forma, depois total: 22.14 e largest: rectangle: 6.00, trabalhando apenas com to_s e area.
Seu código deve estar em shape.rb, circle.rb, rectangle.rb e triangle.rb. main.rb contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
require_relative 'shape'
require_relative 'circle'
require_relative 'rectangle'
require_relative 'triangle'
# Código de entrada/saída fornecido: mantenha-o como está
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)}"
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação orientada a objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesVariáveis de InstânciaMétodos e selfto_s e inspectRevisão - Cartão da Biblioteca4Encapsulamento
Métodos privadosMétodos protegidosSetters privadosProtegendo o estadoRevisão - Máquina de venda automática7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMétodos Abstratoscase e ClassesRevisão - Métodos de Pagamento2Acessores e self
Leitores e GravadoresSetters Personalizadosself nos MétodosIdentidade e IgualdadeRecapitulação - Lista de Contatos5Herança
SubclassesSobrescrita de métodosChamando superis_a? e ancestraisRevisão - Folha de pagamento da equipe8Métodos Especiais
Igualdade e hashMétodos de OperadoresIndexação e AdiçãoColeções PersonalizadasRevisão - Frações11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de Ruby online