Polimorfismo
Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 32 di 57.
Polimorfismo significa che una chiamata di metodo funziona su oggetti di classi diverse e che ogni oggetto risponde a modo proprio. Il codice che scorre le forme chiama area su ciascuna senza chiedere di che tipo di forma si tratti:
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, chi chiama 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.areaAggiungere 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 di uso quotidiano: 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 cifre 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, usando solo 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