rails控制器中的实例和类变量

Fin*_*nks 21 ruby ruby-on-rails

我是铁杆和红宝石的新手.我正在研究类和实例变量的概念.我明白了区别,但是当我在轨道上使用控制器尝试它时,让我感到困惑.我所做的是在类方法之外声明了一个类和实例变量:

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
Run Code Online (Sandbox Code Playgroud)

我的印象是@insworld具有"我的爱好"的价值,但是当我在里面时,当我试图检查@insworld的价值时index method,@ insworld返回了一个零值.@@ world具有"Hello World"的价值.那么这里发生了什么?它们不是在同一个类中定义的吗?

Agi*_*gis 48

类也是Ruby中的对象,因此它们可以拥有自己的实例变量,这些变量称为类实例变量.

  • @@world是一个类变量
  • @insworld是一个类实例变量
  • #index 是一个实例方法

当您尝试访问@insworld#index,Ruby会在A对象中搜索实例变量(含义A.new),因为它#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
Run Code Online (Sandbox Code Playgroud)

请记住,nil如果它们不存在,则返回所有实例变量.


Bro*_*tse 6

当你声明@instworld你在BooksController类中时(self即将返回BooksController.在ruby中奇怪的是类也是对象(类的实例Class)因此你实际上@instworld为这个特定的Classm 类实例声明了实例变量而不是例如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'
Run Code Online (Sandbox Code Playgroud)