Polimorfismo
Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 32 di 57.
Polimorfismo significa che una chiamata a un metodo funziona su oggetti di classi diverse e che ogni oggetto risponde a modo suo. Il codice che scorre le forme chiama area su ciascuna senza chiedere che tipo di forma sia:
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))Output:
circle 3.14
square 9.00
total 12.14Senza polimorfismo, il chiamante deve controllare il tipo di ogni oggetto e ripetere quel controllo ovunque la differenza sia rilevante. Con il polimorfismo, la differenza risiede all’interno di ogni classe:
# senza polimorfismo
case shape.kind
when "circle" then 3.14159 * shape.r ** 2
when "square" then shape.side ** 2
end
# con polimorfismo
shape.areaL'aggiunta di un nuovo tipo di oggetto non richiede quindi modifiche al codice chiamante: una nuova sottoclasse con il proprio area funziona in ogni ciclo già esistente:
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 }Output:
area 4
area 6to_s è l'esempio più comune: puts lo chiama su qualsiasi oggetto e ogni classe risponde in modo diverso. Anche le tue classi partecipano definendo il proprio to_s:
class Coin
def to_s
"a coin"
end
end
[42, "text", nil, [1, 2], Coin.new].each { |x| puts "[#{x}]" }Output:
[42]
[text]
[]
[[1, 2]]
[a coin]Sfida
FacileCompleta le forme. Shape#to_s restituisce circle: 3.14, il nome della classe in minuscolo e l'area con due decimali, e ogni sottoclasse fornisce area: Circle.new(r) (usa 3.14159 per pi), Rectangle.new(w, h) e Triangle.new(base, height).
Il codice fornito legge righe circle 1, rectangle 2 3 o triangle 4 5, stampa ogni forma, poi total: 22.14 e largest: rectangle: 6.00, funzionando solo con to_s e area.
Il tuo codice va in shape.rb, circle.rb, rectangle.rb e triangle.rb. main.rb contiene il codice di input/output fornito e non può essere modificato.
Provalo tu
require_relative 'shape'
require_relative 'circle'
require_relative 'rectangle'
require_relative 'triangle'
# Supplied input/output code: keep it as it is
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)}"
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Classi e oggetti
Lavorare con i fileDefinire le classiVariabili d'istanzaMetodi e selfto_s e inspectRipasso - Tessera della biblioteca4Incapsulamento
Metodi privatiMetodi protettiSetter privatiProteggere lo statoRiepilogo - Distributore automatico7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMetodi astratticase e classiRiepilogo - Metodi di pagamento10Pattern di progettazione Parte 2
Delegazione con ForwardablePattern DecoratorPattern BuilderPattern State2Metodi di accesso e self
Metodi di lettura e scritturaSetter personalizzatiself nei metodiIdentità e uguaglianzaRiepilogo - Elenco contatti5Ereditarietà
SottoclassiRidefinizione dei metodiChiamare superis_a? e antenatiRiepilogo - Paghe del personale8Metodi speciali
Uguaglianza e hashMetodi degli operatoriIndicizzazione e appendCollezioni personalizzateRiepilogo - Frazioni11Progetto: Gestione della biblioteca
Libri e iscrittiPrendere in prestito i libriEsercitati da solo: Compilatore Ruby online