I’m still learning Ruby, and I’m curious about whether it is appropriate to use a class variable, constant, or local variable in this scenario.
In my below code example (that generates random usernames out of a fixed character set), assigning @username
as an instance variable is fairly obvious. But I’m curious whether I should assign the charset as a constant or maybe a class variable. What would be the advantages of using another variable type in this scenario?
In the current example, the _charset
is computed in every instance. (Do correct me if my assumption is wrong.) I also assume the computation would be shared between instances (as opposed to recomputed) as both a class variable and as a constant?
class NewAccount
def initialize
@username = self.generate_username
end
def generate_username
_charset = ('a'..'z').to_a + ('0'..'9').to_a
_newusername = Array.new(20) { _charset[rand(_charset.length)] }.join
retur开发者_如何学JAVAn _newusername
end
end
You can make it a class variable or constant, actually this would be the same: only one instance would exist. And Ruby constants are not really constants - you can change a constant so it is really a variable, only because of its name Ruby recognizes a constant and issue a warning if you try to change it.
But by declaring it as a constant and not a class variable you are documenting your aim: to have a constant value consisting of a character set, that is not designed to be changed. This will be obvious for anybody reading the code. This is what you want the character set for - so do it.
If you make it a class variable it will be a variable: so no problem if somebody tries to change. Of course if you plan on changing its value for whatever reason do it a class variable: again you will document your design.
Because _charset = ('a'..'z').to_a + ('0'..'9').to_a
never changes from its definition, I'd create it as a class constant:
class NewAccount
CHARSET = ('a'..'z').to_a + ('0'..'9').to_a
def initialize
@username = self.generate_username
end
def generate_username
_newusername = Array.new(20) { CHARSET[rand(CHARSET.length)] }.join
return _newusername
end
end
I think you can make it class variable as the _charset is going to be used in NewAccount class only and its value would not be changed for NewAccount's instance.
In your example the @username would be computed once for each instance, and the _charset only computed once in your example– but the _charset is only a local variable, so it would be recomputed if you ran the method twice.
What you want is what the Tin Man suggests, set it as a constant and compute it once. Using a class-varible (@@charset) could be misleading as the charset is not intended to change at any point.
精彩评论