2014-01-23 41 views
14

我是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正在返回一個零值。 @@世界具有「Hello World」的價值。那麼這裏發生了什麼?他們不是在同一個班級中定義的嗎?

+0

你可能要檢查的接受answe對於這個SO問題:http://stackoverflow.com/questions/3802540/difference-between-class-variables-and-class-instance-variables – lucke84

回答

39

類也是Ruby中的對象,因此它們可以擁有自己的實例變量,這些變量被稱爲類實例變量

  • @@world類變量
  • @insworld類實例變量
  • #index是一個實例方法

當您嘗試訪問@insworld#index,紅寶石搜索A對象中的實例變量(意爲A.new)beca使用#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如果他們不存在。

2

實例變量的作用域來自動作,以便在發生任何操作時啓動並在動作結束時將其銷燬。

+0

所以你如何有一個真正的類實例變量,一個堅持所有行動? @ahmad Hussain – conterio

2

當你在方法外聲明實例變量時,你可能不會得到你想要的結果。它是一個實例變量,是的,但它屬於類本身(它是類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 

如果您嘗試獲得未初始化的伊娃的價值,它將評估爲nil。這就是爲什麼你在實驗中得到了nil:變量在該範圍內不存在。

要獲取實例級別的變量,請在方法/操作中設置它們。

1

在類中聲明@insworld,但在構造函數或任何實例方法中聲明@insworld將@insworld範圍設置爲該類本身的實例。

BooksController.instance_variable_get(:'@insworld') 

如果你需要你的索引方法的內部訪問的變量,可以考慮在方法中定義它來代替。

5

當你聲明@instworld你BooksController中類中(即self將返回BooksController。在紅寶石奇怪的是,類也是對象(的是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'