Per farla breve:
(object = Object.new).instance_eval &block
set:
Object.class_eval &block
set:
self
a Object
- La "classe corrente" per
Object
La "classe corrente" viene utilizzato per def
, undef
e alias
, nonché le ricerche variabili e costanti di classe.
Ora, diamo un'occhiata ai dettagli di implementazione.
Ecco come module_eval
e instance_eval
sono implementate in C:
VALUE rb_mod_module_eval(int argc, VALUE *argv, VALUE mod) {
return specific_eval(argc, argv, mod, mod);
}
VALUE rb_obj_instance_eval(int argc, VALUE *argv, VALUE self) {
VALUE klass;
if (SPECIAL_CONST_P(self)) { klass = Qnil; }
else { klass = rb_singleton_class(self); }
return specific_eval(argc, argv, klass, self);
}
Entrambi chiamata specific_eval
, che accetta i seguenti argomenti: int argc
, VALUE *argv
, VALUE klass
e VALUE self
.
noti che:
module_eval
passa l'istanza Module
o Class
sia come klass
eself
instance_eval
passa classe singleton dell'oggetto come klass
Se in un blocco , specific_eval
chiamerà yield_under
, che accetta i seguenti argomenti: VALUE under
, VALUE self
e VALUE values
.
if (rb_block_given_p()) {
rb_check_arity(argc, 0, 0);
return yield_under(klass, self, Qundef);
}
Ci sono due linee importanti yield_under
:
block.self = self;
Imposta la self
del blocco al ricevitore.
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
Il cref
è una lista collegata che specifica la "classe di", che viene utilizzato per def
, undef
e alias
, nonché ricerche variabili come costanti e di classe.
Questa riga imposta in pratica lo cref
su under
.
Infine:
Quando chiamato da module_eval
, under
sarà l'istanza Class
o Module
.
Quando viene chiamato da instance_eval
, under
sarà la classe Singleton di self
.
fonte
2012-04-24 21:11:22
c'è una cosa: dentro 'class_eval' assegnazione di costanti e variabili di classe non funziona il modo in cui funziona nella definizione di classe/riapertura: si usa l'ambito esterno. – Alexey
@Alexey, hai ragione. Scommetto che ha qualcosa a che fare con la costante di 'NODE_FL_CREF_PUSHED_BY_EVAL'. Molti metodi, come ['Module :: nesting'] (http://ruby-doc.org/core-1.9.3/Module.html#method-c-nesting), ad esempio, sembrano ignorare un nodo' cref' se la bandiera è impostata. –