수색…


통사론

  • $ global_variable
  • @@ class_variable
  • @instance_variable
  • local_variable

비고

클래스 변수는 클래스 계층에서 공유됩니다. 이것은 놀라운 결과를 초래할 수 있습니다.

class A
  @@variable = :x

  def self.variable
    @@variable
  end
end

class B < A
  @@variable = :y
end

A.variable  # :y

클래스는 객체이므로 인스턴스 변수를 사용하여 각 클래스에 고유 한 상태를 제공 할 수 있습니다.

class A
  @variable = :x

  def self.variable
    @variable
  end
end

class B < A
  @variable = :y
end

A.variable  # :x

지역 변수

지역 변수 (다른 변수 클래스와 달리)에는 접두사가 없습니다.

local_variable = "local"
p local_variable
# => local

범위는 선언 된 위치에 따라 다르며 "선언 컨테이너"범위 외부에서 사용할 수 없습니다. 예를 들어 로컬 변수가 메소드에서 선언 된 경우 해당 메소드 내에서만 사용할 수 있습니다.

def some_method
    method_scope_var = "hi there"
    p method_scope_var
end

some_method
# hi there
# => hi there

method_scope_var
# NameError: undefined local variable or method `method_scope_var'

물론, 지역 변수는 메소드에 국한되지 않으며, do ... end 블록 내에서 변수를 선언하거나 중괄호 {} 묶는 즉시 로컬과 범위로 블록이 선언되었다.

2.times do |n|
    local_var = n + 1
    p local_var
end
# 1
# 2
# => 2

local_var
# NameError: undefined local variable or method `local_var'

그러나 if 또는 case 블록에 선언 된 지역 변수는 부모 범위에서 사용할 수 있습니다.

if true
    usable = "yay"
end

p usable
# yay
# => "yay"

지역 변수는 선언 블록 외부에서 사용할 수 없지만 블록으로 전달됩니다.

my_variable = "foo"

my_variable.split("").each_with_index do |char, i|
    puts "The character in string '#{my_variable}' at index #{i} is #{char}"
end
# The character in string 'foo' at index 0 is f
# The character in string 'foo' at index 1 is o
# The character in string 'foo' at index 2 is o
# => ["f", "o", "o"]

그러나 메소드 / 클래스 / 모듈 정의가 아닙니다.

my_variable = "foo"

def some_method
    puts "you can't use the local variable in here, see? #{my_variable}"
end

some_method
# NameError: undefined local variable or method `my_variable'

블록 인수에 사용 된 변수는 (물론) 블록에 국한되지만, 이전에 정의 된 변수를 덮어 쓰지 않고 덮어 씁니다.

overshadowed = "sunlight"

["darkness"].each do |overshadowed|
    p overshadowed
end
# darkness
# => ["darkness"]

p overshadowed
# "sunlight"
# => "sunlight"

클래스 변수

클래스 변수는 클래스 범위가 넓어 클래스의 어느 위치에서나 선언 할 수 있습니다. @@ 접두사가 붙은 변수는 클래스 변수로 간주됩니다.

class Dinosaur
    @@classification = "Like a Reptile, but like a bird"
    
    def self.classification
        @@classification
    end

    def classification
        @@classification
    end
end

dino = Dinosaur.new
dino.classification
# => "Like a Reptile, but like a bird"
  
Dinosaur.classification
# => "Like a Reptile, but like a bird"

클래스 변수는 관련 클래스간에 공유되며 자식 클래스에서 겹쳐 쓸 수 있습니다.

class TRex < Dinosaur
    @@classification = "Big teeth bird!"
end

TRex.classification
# => "Big teeth bird!"

Dinosaur.classification
# => "Big teeth bird!"

이 동작은 대부분 원하지 않으므로 클래스 수준 인스턴스 변수를 사용하여 피할 수 있습니다.

모듈 안에 정의 된 클래스 변수는 클래스를 포함하는 클래스를 덮어 쓰지 않습니다 :

module SomethingStrange
    @@classification = "Something Strange"
end

class DuckDinosaur < Dinosaur
    include SomethingStrange
end

DuckDinosaur.class_variables
# => [:@@classification]
SomethingStrange.class_variables
# => [:@@classification]

DuckDinosaur.classification
# => "Big teeth bird!"

전역 변수

전역 변수는 전역 범위를 가지므로 모든 곳에서 사용할 수 있습니다. 범위는 정의 된 위치에 의존하지 않습니다. 변수는 $ 기호를 접두사로 사용하여 전역 변수로 간주됩니다.

$i_am_global = "omg"

class Dinosaur
    def instance_method
       p "global vars can be used everywhere. See? #{$i_am_global}, #{$another_global_var}" 
    end

    def self.class_method
       $another_global_var = "srsly?"
       p "global vars can be used everywhere. See? #{$i_am_global}"
    end
end

Dinosaur.class_method
# "global vars can be used everywhere. See? omg"
# => "global vars can be used everywhere. See? omg"

dinosaur = Dinosaur.new
dinosaur.instance_method
# "global vars can be used everywhere. See? omg, srsly?"
# => "global vars can be used everywhere. See? omg, srsly?"

전역 변수는 어디에나 정의 될 수 있고 모든 곳에서 볼 수 있기 때문에 "정의되지 않은"전역 변수를 호출하면 오류가 발생하는 대신 nil이 반환됩니다.

p $undefined_var
# nil
# => nil

전역 변수는 사용하기 쉽지만 사용법은 상수를 사용하는 것이 좋습니다.

인스턴스 변수

인스턴스 변수는 객체 범위가 넓으며 객체의 어느 위치에서나 선언 할 수 있지만 클래스 수준에서 선언 된 인스턴스 변수는 클래스 객체에서만 볼 수 있습니다. 변수는 접두사 @ 가 붙은 경우 인스턴스 변수로 간주됩니다. 인스턴스 변수는 객체 속성을 설정하고 가져 오는 데 사용되며 정의되지 않은 경우 nil을 반환합니다.

class Dinosaur
    @base_sound = "rawrr"

    def initialize(sound = nil)
        @sound = sound || self.class.base_sound
    end

    def speak
        @sound
    end

    def try_to_speak
        @base_sound
    end

    def count_and_store_sound_length
        @sound.chars.each_with_index do |char, i|
            @sound_length = i + 1
            p "#{char}: #{sound_length}"
        end
    end
    
    def sound_length
        @sound_length
    end

    def self.base_sound
        @base_sound
    end
end

dino_1 = Dinosaur.new
dino_2 = Dinosaur.new "grrr"

Dinosaur.base_sound
# => "rawrr"
dino_2.speak
# => "grrr"

클래스 수준에서 선언 된 인스턴스 변수는 개체 수준에서 액세스 할 수 없습니다.

dino_1.try_to_speak
# => nil

그러나 새 메서드에 소리가 전달되지 않을 때 인스턴스 변수 @base_sound 를 사용하여 사운드를 인스턴스화했습니다.

dino_1.speak
# => "rawwr"

인스턴스 변수는 블록 내부에서도 객체의 어느 위치에서나 선언 할 수 있습니다.

dino_1.count_and_store_sound_length
# "r: 1"
# "a: 2"
# "w: 3"
# "r: 4"
# "r: 5"
# => ["r", "a", "w", "r", "r"]

dino_1.sound_length
# => 5

인스턴스 변수는 같은 클래스의 인스턴스간에 공유 되지 않습니다.

dino_2.sound_length
# => nil

클래스가 Ruby의 객체이기 때문에 하위 클래스에서 덮어 쓰지 않는 클래스 수준 변수를 만드는 데 사용할 수 있습니다.

class DuckDuckDinosaur < Dinosaur
    @base_sound = "quack quack"
end

duck_dino = DuckDuckDinosaur.new
duck_dino.speak
# => "quack quack"
DuckDuckDinosaur.base_sound
# => "quack quack"
Dinosaur.base_sound
# => "rawrr"


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow