2009-05-10 13 views
9

Come faccio a creare la mia classe che può essere sostituita a IO per ad es. reindirizzare/catturare input/output per un codice che accetta un parametro simile all'IO? Lo stesso IO sembra essere accoppiato a descrittori di file OS e l'unica classe che conosco che lo imita senza sottoclassi è StringIO, che sembra reimplementare l'intera interfaccia.Come si crea una sottoclasse personalizzata di IO in Ruby?

Penso che il linguaggio potrebbe fornire un modo semplice per farlo, ma non riesco a trovare alcuna informazione sull'argomento. Esiste un mixin che implementa l'interfaccia su alcuni primitivi, come fa Enumerable?

risposta

4

ho il sospetto che mi manca qualcosa, ma supponendo che non è il caso ...

Perché sarebbe sottoclasse non può essere un'opzione? Non potresti semplicemente scavalcare le parti di IO che devono comportarsi diversamente?

class MyIO < IO 
    # your modified methods go here. e.g. 
    def some_io_method(args) 
    do_some_preprocessing 
    super(args) 
    do_some_post_processing 
    end 
end 

Se non è possibile sostituire la sottoclasse birra fatta in casa, cosa sulla modifica IO se stesso ("scimmia-patching") qualcosa come:

class IO 
    alias_method :original_some_io_method, :some_io_method 
    def some_io_method(args) 
    do_some_preprocessing 
    original_some_io_method(args) 
    do_some_post_processing 
    end 
end 
+3

Il problema è che ci sono metodi di hojillion che leggono/scrivono dati e reimplementarli tutti è noioso. Enumerable implementa esplicitamente tutto in #each, quindi sovrascrivendo #each, si ottiene tutto gratuitamente ". Non capisco perché IO ​​non funzioni allo stesso modo o perché i mixin che sto scrivendo per realizzare questo non esistono già. L'altra cosa strana è che IO è così specializzato, con metodi come sys * che non appartengono ad altre implementazioni. Questo può essere risolto ma non è l'ideale. – jedediah

1

Ho usato con successo i seguenti hack per rendere StringIO un IO "reale":

# make mechanize believe our address xml actually is an IO so it will be uploaded as a file: 
    address_io = StringIO.new(address_xml) 
    class << address_io 
     alias is_a_old is_a? 
     def is_a?(stuff) 
     stuff == IO || is_a_old(stuff) 
     end 
     def path 
     'address.xml' 
     end 
    end 
+0

Ho provato questo con la libreria su cui sto lavorando e in alcuni casi ha causato l'impazzire del codice nativo nell'interprete. Usare con cautela. Inoltre, poiché << address_io è una sottoclasse di StringIO, l'aliasing non è necessario. Basta ignorare il metodo e chiamare super. – jedediah

Problemi correlati