Carissimi lettori,
vi illustro il seguente problema relativo alla chiamata di un metodo di
una classe ereditata.
Ho due classi Time1 e Time2 che ereditano in cascata da Time (tralascio
i metodi particolari)
class Time1 < Time
…
end
class Time2 < Time1
…
end
t = Time2.now
r = t + 3600 # adding 1 hour
purtroppo ora r di class Time, e invece vorrei che rimanesse di classe
uguale a quella di partenza, ovvero Time2.
Allora introduco in Time dei metodi per “ricastare” e modifico come qui
di seguito:
Time.class_eval do
def to_time2
Time2.parse(to_s)
end
def to_time1
Time1.parse(to_s)
end
end
class Time1 < Time
def +(seconds)
super(seconds).to_time1
end
end
class Time2 < Time1
def +(seconds)
super(seconds).to_time2
end
end
r = Time2.now + 3600
ora r correttamente di class Time2, tuttavia ci sono 2 casting in
cascata che suppongo poco performanti
Come posso modificare il codice affinch quando chiamo un metodo di
istanza di Time da un’istanza di classe che eredita da essa (cio Time1 o
Time2) il tipo del valore ritornato sia uguale a quella del chiamante?
direi che in generale l’approccio è corretto, perché il metodo ‘+’ di
Time
restituisce un oggetto di tipo Time; quindi se vuoi che restituisca
qualcos’altro devi ricastare l’oggetto alla classe che desideri (se vuoi
usare super), oppure ridefinire completamente il metodo in modo da
sostituirne integralmente il comportamento.
L’unico problema che vedo con il tuo codice è che viola il principio OOP
che le classi madri non dovrebbero mai sapere nulla delle classi figlie,
mentre tu stai inserendo i metodi ‘to_time1’ e ‘to_time2’ che vanno a
sporcare la classe madre con specifiche implementazioni delle classi
figlie. Quello che farei io è qualcosa di questo tipo: