In Ruby, isn't an instance variable like @foo
and a class variable, @@bar
?
In some code, I see a few
self.user_name = @name
or even
a += 1 if name != user_name # this time, without the "self."
# and it is the first line of a method so
开发者_StackOverflow社区 # it doesn't look like it is a local variable
what is the self for? I thought it might be an accessor, but then can't it be just user_name instead of self.user_name? And I don't even see any code to make it an accessor, like attr_accessor
, and not in the base class either.
In Ruby:
@foo
is an instance variable@@bar
is a class variable
Instance and class variables are private by default. It means, you can't set or get the value outside the class or the module itself.
If you want to set a value for foo
, you need an attribute accessor.
class Model
def foo
@foo
end
def foo=(value)
@foo = value
end
end
For convenience (and performance reason), this is the same of
class Model
attr_accessor :foo
end
Then you can do
m = Model.new
m.foo = "value"
And within the class you can doo
class Model
# ...
def something
self.foo = "value"
# equivalent to
@foo = value
end
end
what is the self for? I thought it might be an accessor
It's a method at least - probably an accessor. self.name = something
will call the method name=
and self.name
, or if no local variable called name
exists, just name
will call the method name
.
but then can't it be just user_name instead of self.user_name?
When invoking the name=
method you need the self
because name = something
would just create a local variable called name
. When invoking the name
method, it doesn't matter whether you write name
or self.name
unless there is also a local variable called name
.
And I don't even see any code to make it an accessor, like attr_accessor, and not in the base class either.
If there is no call to attr_accessor
and no explicit definition of name
and name=
anywhere, they might be handled by method_missing
or defined by a different method than attr_accessor
.
isn't self.user_name the same as @user_name
Only if it's defined to be. If you define user_name
and user_name=? using
attr_accessorthey will get and set
@user_name`. However if you define them through other means (or manually), they can do whatever you want.
For example ActiveRecord uses method_missing
to "define" getter and setter methods that correspond to data base columns. So if your ActiveRecord class belongs to a table with a user_name
column, you'll have user_name
and user_name=
methods without defining them anywhere. The values returned by user_name
and set by user_name =
will also not correspond to instance variables. I.e. there will be no instance variable named @user_name
.
Another way to automatically define user_name
and user_name=
without using instance variables is Struct
:
MyClass = Struct.new(:user_name)
Here MyClass
will have the methods user_name
and user_name=
, but no instance variable @user_name
will be set at any point.
Welcome in the "scope" hell!
Of course, if we have the full code, it should be easier to explain what you see.
Let me try:
class Woot attr_accessor :name def initialize self.name = 'Bistromathic Drive' end def foo puts name # hum… I don't know name. An attr? Oh Yes! name = '42' # New local var named 'name' puts name # Yeah! I know a local named 'name' puts self.name # I know the attr named 'name' name = 'Improbability Drive' # Change the local puts name puts self.name # attr didn't move self.name = 'What was the question?' puts name puts self.name end end w = Woot.new w.foo # => Bistromathic Drive 42 Bistromathic Drive Improbability Drive Bistromathic Drive Improbability Drive What was the question?
The partial code you show is "suspect" to me, and I'd prefer to explain the base of var scope.
精彩评论