2012-01-30 7 views
10

Qual è la differenza quando facciorubino self.class.class_eval o singleton_class.class_eval

class T 

    def initialize 
    self.class.class_eval do 
     def test 
     return self.class.object_id 
    end 
    end 
    end 

end 

e

class T 

    def initialize 
    singleton_class.class_eval do 
     def test 
     return self.class.object_id 
    end 
    end 
    end 

end 

Grazie

PS. Tass ha risposto che in questo esempio, singleton_class restituirà un diverso object_id per ciascun nuovo oggetto, poiché un singleton_class appartiene a un solo oggetto. Ma mostra IRB prossimo

1.9.2p180 :001 > class T 
1.9.2p180 :002?> 
1.9.2p180 :003 >  def initialize 
1.9.2p180 :004?>  singleton_class.class_eval do 
1.9.2p180 :005 >    def test 
1.9.2p180 :006?>     return self.class.object_id 
1.9.2p180 :007?>    end 
1.9.2p180 :008?>  end 
1.9.2p180 :009?>  end 
1.9.2p180 :010?> 
1.9.2p180 :011 >  end 
=> nil 
1.9.2p180 :012 > t = T.new 
=> #<T:0x00000100ae9cb8> 
1.9.2p180 :013 > t1 = T.new 
=> #<T:0x00000100ad7ef0> 
1.9.2p180 :014 > t1.test == t.test 
=> true 
1.9.2p180 :015 > t1.test 
=> 2153233300 
1.9.2p180 :016 > t.test 
=> 2153233300 
1.9.2p180 :017 > 
+1

Non riesco a trovare alcuna differenza funzionale, ma penserei che dovrebbe essercene uno. –

+2

@JakubHampl, sembra che ho trovato la differenza) –

+1

@AlexKliuchnikau Sapevo che qualcuno lo avrebbe fatto. +1 a te! –

risposta

10

La differenza tra le istanze di questi T classi è nell'algoritmo di metodo di ricerca: il metodo è sempre cercato nella classe Singleton (e dei suoi moduli) e solo se non si trova qui, viene cercato nella classe .

Questo significa che se si aggiunge il metodo test per la prima implementazione di classe T dopo l'inizializzazione avremo risultato diverso rispetto a quando facciamo lo stesso per la seconda implementazione di classe T:

# First example 
class T 
    def initialize 
    self.class.class_eval do 
     def test 
     return self.class.object_id 
     end 
    end 
    end 
end 

t = T.new 

class T 
    def test 
    'overriden' 
    end 
end 

puts t.test # => 'overriden' 

class T 
    def initialize 
    singleton_class.class_eval do 
     def test 
     return self.class.object_id 
     end 
    end 
    end 
end 

t = T.new 

class T 
    def test 
    'overriden' 
    end 
end 

puts t.test # => 77697390 
+0

grazie per la risposta! ora vedo la differenza) – Fivell

+0

Da un punto di vista pratico, quando dovresti fare uno rispetto all'altro? – Claw

+0

@Claw, i metodi sopra sono solo dei campioni di prova curiosi, non vorrei scrivere nulla di simile nell'inizializzatore della classe reale. Generalmente: aggiungi metodi alla * classe * quando devi aggiungere il metodo a * tutte * le istanze della classe e aggiungi il metodo a * singleton class * quando devi aggiungere il metodo a un'istanza * single * della classe. Nell'esempio 2 OP aggiunge il metodo a * singleton class * di * each * method instance (in initializer) - questo non è pratico, aggiungi un metodo a * class * in tali situazioni. –

7

singleton_class ti dà la Class che è unico per quell'oggetto. self.class fornisce la classe per cui tutti gli oggetti di quella condivisione Class. Example

foobar = Array.new 

# this defines a method on the singleton class 
def foobar.size 
    "Hello World!" 
end 

foobar.size # => "Hello World!" 
foobar.class # => Array 

bizbat = Array.new 
bizbat.size # => 0 

Nell'esempio precedente, singleton_class restituirà un diverso object_id per ogni nuovo oggetto, perché un singleton_class appartiene a un solo Object. self.class restituirà lo stesso perché self.class punta allo stesso Class ogni volta.

+2

Questo segue praticamente direttamente dai documenti. Ma non è una risposta alla domanda. Che differenza fanno effettivamente i due approcci nel codice sopra? –

+1

Sembra che l'OP non chieda quale sia la differenza tra classe e classe singleton, ma qual è la differenza tra questi due esempi forniti dal punto di vista dell'esecuzione del programma. In entrambi i casi le istanze di 'T' avranno istanza con il metodo' test', e in che modo sono differenti? –

+0

grazie per la risposta, Alex, certo, voglio capire la diffrerence di cui hai parlato – Fivell