2010-07-07 9 views
12

Posso creare classi Ruby all'interno dei corpi delle funzioni? Sembra che stia ricevendo un errore che mi dice che non è permesso ma penso che dovrebbe esserlo visto che le classi sono troppo oggetti qui.Perché non ci sono classi nei metodi in Ruby?

 
class A 
    def method 
     class B 
     end 
    end 
end

Questo errore con l'errore 'definizione della classe all'interno del corpo del metodo. Se non possiamo, perché non possiamo creare classi all'interno dei metodi?

+2

perché vorresti mai fare questo? –

+0

@Mark: lo faccio sempre con oggetti anonimi in C#. Certo, non hanno metodi di per sé, ma è ancora un valido motivo per voler creare una classe al volo. Un oggetto contenitore di breve durata che trattiene temporaneamente alcuni dati che posso usare in maniera fortemente tipizzata (almeno facendo riferimento alle proprietà per nome) è una cosa davvero utile da avere in giro. – tvanfosson

+0

@ Mark- esattamente come ha detto tvanfosson! –

risposta

8
class A 
    def method 
    self.class.const_set :B, Class.new { 
     def foo 
     'bar' 
     end 
    } 
    end 
end 

A.new.method 
A::B.new.foo # => 'bar' 

Tuttavia, perché si desidera assegnare una costante all'interno di un metodo? Ciò non ha senso: le costanti sono costante, è possibile assegnarle solo una volta, il che significa che è possibile eseguire il metodo una sola volta. Quindi, perché scrivi un metodo, se mai verrà eseguito una volta sola, comunque?

+4

Riesco a pensare a diversi schemi che potrebbero definire le classi in un metodo, in particolare cose come ponti, adattatori e fabbriche. Sarebbe utile se hai bisogno di ottenere qualche risorsa statica (come una connessione LDAP), ma non vuoi dettare l'implementazione (ad esempio net/ldap vs ruby-net-ldap). Tuttavia, è lontano da una necessità quotidiana. –

+0

Voglio che la classe sia locale all'istanza di azione. In modo che le istanze di classe siano destinate a essere raccolte automaticamente dopo che l'azione è stata completata.Vale a dire, faccio una richiesta di sapone, la analizzo come istanze di qualche classe (in modo che rispondano ad alcune chiamate). E passa '@ cose' alla vista. Una volta resa la vista, non voglio ricordare '@ things' affatto. – Adobe

10

è possibile creare classi, ma non è possibile assegnare costanti all'interno di un metodo.

questo esempio funziona:

class A 
    def a 
    b = Class.new 
    def b.xxx 
     "XXX" 
    end 
    b 
    end 
end 

a = A.new.a 
p a   # #<Class:0x7fa74fe6cc58> 
p a.xxx  # "XXX" 
+0

Questa è una risposta migliore. OP voleva sapere ** perché **. Hai spiegato perché. –

+0

La sua domanda riguardava la definizione di una classe all'interno di un metodo, non la creazione di una istanza. Questa risposta non affronta la domanda. – Gewthen

8

è possibile creare classi dall'interno metodi e assegnarli a una costante, come nel seguente

class A 
    def create_class class_name 
    new_class = Class.new 
    new_class.send :define_method, :speak do 
     "Hi, There" 
    end 
    Object.const_set class_name, new_class 
    end 
end 

A.new.create_class "Harry" 
h = Harry.new 
puts h.speak # responds => "Hi, There" 

perché un nome di classe come in String è solo una costante nel rubino a differenza di molte altre lingue.

4

La domanda è sulla creazione di classi, ma nel commento si parla di creare oggetti anonimi . Non è la stessa cosa

Se è necessario un oggetto anonimo, è sempre possibile eseguire Object.new. Se hai bisogno di un semplice contenitore simile a una struct, dovresti dare un'occhiata alla classe Struct. Con esso, si può fare qualcosa di simile:

def foo 
    anon_obj = Struct.new(:prop1, :prop2).new 
    anon_obj.prop1 = 123 
    anon_obj.prop2 = 'bar' 

    return anon_obj 
end 

BTW, Ruby è un linguaggio fortemente tipizzato. Ma è anche una digitazione dinamica, e non ci si può aspettare che si comporti come una tipizzazione statica.

Problemi correlati