2012-01-18 14 views
11

Ho pensato che questa domanda (How to do attr_accessor_with_default in ruby?) ha risposto alla mia domanda, ma non sto usando ActiveRecord e after_initialize dipende da questo.il modo migliore per impostare un valore predefinito su una proprietà senza ActiveRecord?

Qual è la best practice di Ruby per l'implementazione di un valore predefinito per un attr_accessor? this è la cosa più vicina alla documentazione a riguardo? Devo smettere di usare attr_accessor dato che è privato?

+0

Non vuoi '@@' vars se non sei SICURO sai perché lo fai. Le variabili di istanza di livello di classe (vedi la mia risposta di seguito) sono un pelo di lavoro in più, ma hanno meno sorprese rispetto alle sottoclassi. Cosa stai cercando di realizzare davvero? – Phrogz

+0

Vedo cosa sta succedendo ora, rimuoverò la modifica. Avevo l'impressione sbagliata che attr_accessor fosse una cosa di Rails. – jcollum

risposta

20
class Foo 
    # class-level instance variable 

    # setting initial value (optional) 
    @class_var = 42 

    # making getter/setter methods on the class itself 
    class << self 
    attr_accessor :class_var 
    end 

    # instance-level variable getter/setter methods 
    attr_accessor :inst_var 
    def initialize 
    # setting initial value (optional) 
    @inst_var = 17 
    end 
end 

p Foo.class_var 
#=> 42 
Foo.class_var = 99 
p Foo.class_var 
#=> 99 

f1 = Foo.new 
f2 = Foo.new 
f2.inst_var = 1 
p [f1.inst_var, f2.inst_var] 
#=> [17,1] 
+2

Ottima risposta, grazie. Che dire di 'attr_accessor' essere privato? È strano venire da C# che Ruby mi permetta di usare cose private come questa. È come se il privato fosse solo un suggerimento. Dispari. – jcollum

+0

Non esegue metodi privati, ma è esso stesso privato: è inteso per essere utilizzato solo quando si apre la classe. Puoi sempre riaprire una classe in un secondo momento, oppure "Foo.instance_eval {attar_accessor: bar}" o usare ['__send__'] (http://www.ruby-doc.org/core-1.9.3/BasicObject. html # method-i -__ send__) che ignora le restrizioni. Sì, Ruby ti dà coltelli affilati con cui giocare, se vuoi. – Phrogz

+0

Hmm, non esattamente quello di cui ho bisogno. Quando faccio '@debug = false class << self attr_accessor: debug end' e creo un'istanza di una classe che eredita da quella classe, la proprietà debug è nulla. Mi aspetto "falso" lì, poiché ha un valore predefinito. Ci scusiamo per la fasulla formattazione. – jcollum

1

@Phrogz ha fornito una buona soluzione, ma dovresti saperne di più.

Qui si crea un class-level instance variable, che non è realmente una variabile di classe, ma a chi importa, perché dopo aver inizializzato una variabile di classe reale con lo stesso nome, si perde un vecchio riferimento.

di ispezionare la falsità, utilizzare il codice precedente, ma con una matrice:

class Foo 
    @class_var = [42] 
    class << self 
    attr_accessor :class_var 
    end 
end 
b = [Foo.class_var] 
Foo.class_var = 69 
p b # still [[42]] 

E si sta per ottenere un problema, quando si cerca di ottenere la variabile tramite @@ che avrebbe dovuto per una classe vera e propria variabile.

class Bar 
    @class_var = [42] 
    class << self 
    attr_accessor :class_var 
    end 
    def biz 
    self.class.class_var 
    end 
    def baz 
    @@class_var 
    end 
end 
p Bar.new.biz # self.class. is kinda a way to emulate the reference from outside 
p Bar.new.baz # and exception, because you don't really have a class variable defined yet! 
Problemi correlati