Domanda

Sono un antipasto di Ruby. Ho scoperto che entrambi sono abbastanza simili (in output), ma non riuscivo a capire la differenza nel contesto seguente. Ad esempio, ho una classe

class Say
  def self.hello
    puts "hello"
  end
end

e può essere esteso in questo modo

class << Say
  def hi
    puts "hi"
  end
end

E anche questo

Say.class_eval do
  def self.bye
    puts "bye"
  end
end

Quando dovrei usare << e quando class_eval?

È stato utile?

Soluzione

class_eval Non ha davvero nulla a che fare con class << className.

A.class_eval do
   ...
end

è equivalente a

class A
  ...
end

con alcune differenze. Class_eval usa un blocco (o una stringa, ma ignorandolo per il momento) il che significa che si chiude sopra l'ambito lessicale contenente. In altre parole puoi usare le variabili locali dall'ambito circostante. Il Common Class Block introduce un ambito nuovo di zecca. Allo stesso modo puoi creare il blocco e passarlo a molte diverse classi di classe_eval e il corpo del blocco verrà eseguito nel contesto della classe su cui stai chiamando Class_Eval.

class << className Apre la classe Singleton di className, permettendoti di definire i metodi di classe.

class << A
  def foo
    ...
  end
end

Equivale a

def A.foo
  ...
end

Si noti che sono metodi di classe Oly se A è una classe (quasi) tutti gli oggetti in Ruby hanno classi singleton e puoi definire metodi per loro usando uno di questi due sintassi. Il vantaggio di class << obj è principalmente se stai definendo molti metodi singleton in una volta.

Altri suggerimenti

Come già detto Class_eval non ha davvero molto a che fare con

class <<self

Anche se sembrano fare la stessa cosa nel tuo esempio (mentre l'effetto è simile, non fa lo stesso, ci sono sottili differenze).

Ecco un altro esempio in cui l'uso della seconda forma è molto più chiaro:

class A

end


a = A.new
b = A.new

class <<b
  def say_hi
    puts "Hi !"
  end
end


b.say_hi # will print "Hi !"
a.say_hi # will raise an undefined method

A e B sono entrambi oggetti della stessa classe A, ma abbiamo aggiunto un metodo alla metaclasse di B, quindi il metodo Say_hi è disponibile solo per l'oggetto B.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top