Ruby Language
가변 범위 및 가시성
수색…
통사론
- $ 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"