Ruby Instance Variables or Local Variables?

2019-06-02 17:03发布

I am new to Ruby language. I understand that

@@count: Class variables
@name: Instance variables
my_string: Local variables

I keep the above in mind. However, I found one Ruby code like this:

class HBaseController < ApplicationController
...
  def result
    conn = OkHbase::Connection.new(host: 'localhost', port: 9090, auto_connect: true)
  ...
  end
end

'conn' confuses me a lot.

Is 'conn' a instance variable, or local variable? And what is the scope of 'conn'?

4条回答
Viruses.
2楼-- · 2019-06-02 17:13

In this case, conn is local variable.

EDIT:

conn would be a instance variable if you had it written like

@conn = OkHbase::Connection.new(host: 'localhost', port: 9090, auto_connect: true)

查看更多
地球回转人心会变
3楼-- · 2019-06-02 17:14

conn is local to the method result

Blocks create a new scope, as do methods and class declarations. Interestingly, if statements do not create a new local scope, so variables you declare inside of an if statement is available outside.

$ irb
1.9.3-p484 :001 > if true
1.9.3-p484 :002?>   foo = 1
1.9.3-p484 :003?>   end
 => 1 
1.9.3-p484 :004 > foo
 => 1 
1.9.3-p484 :005 > 1.times do
1.9.3-p484 :006 >     bar = 1
1.9.3-p484 :007?>   end
 => 1 
1.9.3-p484 :008 > bar
NameError: undefined local variable or method `bar' for main:Object
    from (irb):8
    from irb:12:in `<main>'
查看更多
唯我独甜
4楼-- · 2019-06-02 17:31

I try to explain it with a little example:

class MyClass
  def meth
    conn = 1
  end
  def result
    conn
  end
end

x = MyClass.new
p x.result #-> test.rb:6:in `result': undefined local variable or method `conn'

conn is unknown. Let's try to call meth before:

class MyClass
  def meth
    conn = 1
  end
  def result
    conn
  end
end

x = MyClass.new
x.meth      # try to create conn
p x.result  #-> test.rb:6:in `result': undefined local variable or method `conn' 

Same result. So conn is no instance variable. You define a local variable in meth but it is unknown outside.

Let's try the same with instance variables:

class MyClass
  def meth
    @conn = 1
  end
  def result
    @conn
  end
end

x = MyClass.new
p x.result  #-> nil (no value assigned (*), but is is existing)
x.meth      # initialze @conn with a value
p x.result  #-> 1

With the usage of accessor-methods you define implicit an instance variable:

class MyClass
  attr_reader :conn
  def meth
    conn = 1
  end
  def result
    conn
  end
end

x = MyClass.new
p x.result  #-> nil (no value assigned (*), but is is existing)
x.meth      #   define conn with a value
p x.result  #-> nil - the instance variable is not changed, a locale variable was used

In method result the conn is the reader method conn. In the method meth it is a locale variable (this can be confusing, because now you have a variable with the same name as a variable.

If you want to change the conn-value in the meth-method you must define a setter and use self.conn:

class MyClass
  attr_reader :conn
  attr_writer :conn
  def meth
    self.conn = 1
  end
  def result
    conn
  end
end

x = MyClass.new
p x.result  #-> nil (not defined yet, but is is existing)
x.meth      #   define conn with a value
p x.result  #-> 1

You can replace attr_reader and attr_writer with attr_accessor.

(*) Remark: I wrote no value assigned - this is not really correct, nil is also a value.

查看更多
孤傲高冷的网名
5楼-- · 2019-06-02 17:31

conn is a local variable (local variables start with a lower case letter or an underscore)

It contains an instance of OkHbase::Connection

Presumably the code that was omitted ... uses that object. Because it's a local variable, once the result method is ended, the local variable will no longer be accessible and the object will be cleared from memory.

(Of course, it's possible the omitted code assigned the object in conn to an instance variable or passed it into some other method that has stored it elsewhere)

查看更多
登录 后发表回答