rails控制器中的实例和类变量
我是铁杆和ruby的新手。 我正在研究类和实例变量的概念。 我理解了差异但是当我在轨道中使用控制器尝试它时让我感到困惑。 我做的是我在类方法之外声明了一个类和实例变量:
class BooksController < ApplicationController # GET /books # GET /books.json @@world = "Hello World" @insworld = "my hobby" def index @books = Book.all binding.pry respond_to do |format| format.html # index.html.erb format.json { render json: @books } end end end
我的印象是@insworld具有“我的爱好”的价值,但是当我在index method
尝试检查@insworld的值时,@ insworld返回了一个零值。 @@ world具有“Hello World”的值。 那么这里发生了什么? 它们不是在同一个类中定义的吗?
类也是Ruby中的对象,因此它们可以拥有自己的实例变量,这些变量称为类实例变量 。
-
@@world
是一个类变量 -
@insworld
是一个类实例变量 -
#index
是一个实例方法
当您尝试在@insworld
中访问@insworld
时,Ruby会在A
对象中搜索实例变量(意思是#index
),因为#index
是一个实例方法。
但是您将@insworld
定义为类实例变量 ,这意味着它在类对象本身中定义(意味着A
)。
以下代码演示:
class Hi @@a = 1 # class variable @b = 2 # class instance variable def initialize @c = 3 # instance variable end def test # instance method, works on objects of class Hi puts @@a # => 1 puts @b # => nil, there is no instance variable @b puts @c # => 3 # we defined this instance variable in the initializer end end Hi.class_variables # => @@a Hi.instance_variables # => @b Hi.new.instance_variables # => @c # Hi is an object of class Class # Hi.new is an object of class Hi
请记住,如果不存在,则所有实例变量都返回nil
。
当您声明@instworld
你在BooksController类中(即self
将返回BooksController
。在ruby中奇怪的是类也是对象(类Class
实例)因此你事实上为这个特定的类实例声明了实例变量@instworld
Class
m不是BooksController
。
您可以通过声明类方法来轻松检查它:
class A # self here returns class A @variable = 'class instance variable' @@variable = 'class variable' def initalize # self here returns the instance @variable = 'instance variable' end def self.test_me # self here returns class A @variable end def test_me # self returns the instance @variable end #class variable is accessible by both class and instance def test_me2 @@variable end def self.test_me2 @@variable end end A.test_me #=> 'class instance variable' A.new.test_me #=> 'instance variable' A.test_me2 #=> 'class variable' A.new.test_me2 #=> 'class variable'
实例变量的范围是从操作到查看它们在任何操作发生时启动,并在操作结束时销毁。
在方法之外声明实例变量时,可能无法获得所需的结果。 它是一个实例变量,是的,但它属于类本身 (它是类Class
一个实例)。
class Foo @myvar = "class-level" def initialize @myvar = 'instance-level' end end f = Foo.new f.class.instance_variable_get(:@myvar) # => "class-level" f.instance_variable_get(:@myvar) # => "instance-level" f.instance_variable_get(:@myvar2) # => nil
如果你试图获得未初始化的ivar的价值,它将评估nil
。 这就是你在实验中得到nil
的原因:变量在那个范围内不存在。
要获取实例级变量,请在方法/操作中设置它们。
在类中声明@insworld而不在构造函数或任何实例方法中声明@insworld作用于类本身的实例。
BooksController.instance_variable_get(:'@insworld')
如果需要访问索引方法中的变量,请考虑在方法中定义它。