Ruby 인스턴스 변수는 언제 설정 되나요?
class Hello
@hello = "hello"
def display
puts @hello
end
end
h = Hello.new
h.display
위의 클래스를 만들었습니다. 아무것도 인쇄하지 않습니다. 클래스 선언 중에 인스턴스 변수 @hello가 설정되었다고 생각했습니다. 그러나 디스플레이 메서드를 호출하면 출력이 'nil'입니다. 이를 수행하는 올바른 방법은 무엇입니까?
Ruby의 인스턴스 변수는 Ruby를 처음 배울 때 약간 혼란 스러울 수 있습니다. 특히 Java와 같은 다른 OO 언어에 익숙한 경우 더욱 그렇습니다.
단순히 인스턴스 변수를 선언 할 수는 없습니다.
루비의 인스턴스 변수에 대해 알아야 할 가장 중요한 것 중 하나는, 따로 @ 기호 접두사 표기법에서,이다 그들이 삶에 그들이에 할당 된 처음 봄 .
class Hello
def create_some_state
@hello = "hello"
end
end
h = Hello.new
p h.instance_variables
h.create_some_state
p h.instance_variables
# Output
[]
["@hello"]
이 메서드 Object#instance_variables
를 사용하여 개체의 모든 인스턴스 변수를 나열 할 수 있습니다 .
일반적으로 initialize 메소드에서 모든 인스턴스 변수를 "선언"하고 초기화합니다. 공개적으로 사용할 수 있어야하는 인스턴스 변수를 명확하게 문서화하는 또 다른 방법은 Module 메서드 attr_accessor
(읽기 / 쓰기), attr_writer
(쓰기) 및 attr_reader
(읽기)를 사용하는 것입니다. 이러한 메서드는 나열된 인스턴스 변수에 대해 다른 접근 자 메서드를 합성합니다.
class Hello
attr_accessor :hello
end
h = Hello.new
p h.instance_variables
h.hello = "hello"
p h.instance_variables
# Output
[]
["@hello"]
인스턴스 변수는 synthesized Hello#hello=
메서드 를 사용하여 할당 될 때까지 생성되지 않습니다 .
kch가 설명한 것과 같은 또 다른 중요한 문제는 클래스를 선언 할 때 활성화 된 다양한 컨텍스트를 인식해야한다는 것입니다. 클래스를 선언 할 때 가장 바깥 쪽 범위 의 기본 수신자 (self) 는 클래스 자체를 나타내는 개체가됩니다. 따라서 코드는 @hello
클래스 수준에서 할당 할 때 먼저 클래스 인스턴스 변수를 만듭니다 .
내부 메서드 self 는 메서드가 호출 @hello
되는 객체이므로 존재하지 않는 객체 의 이름 으로 인스턴스 변수의 값을 인쇄하려고 합니다 (존재하지 않는 인스턴스를 읽는 것은 완벽하게 합법적입니다. 변하기 쉬운).
initialize
메소드 를 추가해야합니다 .
class Hello
def initialize
@hello = "hello"
end
def display
puts @hello
end
end
h = Hello.new
h.display
@hello
코드에서 첫 번째 는 클래스 인스턴스 변수라고합니다.
상수가 Hello
가리키는 클래스 객체의 인스턴스 변수입니다 . (그리고 이것은 클래스의 인스턴스입니다 Class
.)
기술적으로 class
범위 내에 self
있으면 현재 클래스의 개체로 설정되고 @variables
현재 self
. 나는 이런 것들을 설명하는 것이 싫다.
The Pragmatic Programmers가 제공하는 $ 5 각 스크린 캐스트 모음을 시청 하면이 모든 것을 얻을 수 있으며 훨씬 더 명확해질 수 있습니다 .
(또는 여기에서 설명을 요청하면 업데이트하려고합니다.)
"The ruby programming language"라는 책에 분명한 설명이 있습니다. 읽어 보면 매우 도움이 될 것입니다. 여기에 붙여 넣습니다 (7.1.16 장에서) :
클래스 정의 내부에서 사용되지만 인스턴스 메서드 정의 외부에서 사용되는 인스턴스 변수는 클래스 인스턴스 변수 입니다.
class Point
# Initialize our class instance variables in the class definition itself
@n = 0 # How many points have been created
@totalX = 0 # The sum of all X coordinates
@totalY = 0 # The sum of all Y coordinates
def initialize(x,y) # Initialize method
@x,@y = x, y # Sets initial values for instance variables
end
def self.new(x,y) # Class method to create new Point objects
# Use the class instance variables in this class method to collect data
@n += 1 # Keep track of how many Points have been created
@totalX += x # Add these coordinates to the totals
@totalY += y
super # Invoke the real definition of new to create a Point
# More about super later in the chapter
end
# A class method to report the data we collected
def self.report
# Here we use the class instance variables in a class method
puts "Number of points created: #@n"
puts "Average X coordinate: #{@totalX.to_f/@n}"
puts "Average Y coordinate: #{@totalY.to_f/@n}"
end
end
......
클래스 인스턴스 변수는 클래스 객체의 인스턴스 변수 일 뿐이므로 attr, attr_reader 및 attr_accessor를 사용하여 이에 대한 접근 자 메서드를 만들 수 있습니다.
class << self
attr_accessor :n, :totalX, :totalY
end
이러한 접근자를 정의하면 원시 데이터를 Point.n, Point.totalX 및 Point.totalY로 참조 할 수 있습니다.
Ruby에 "클래스 인스턴스 변수"개념이 있다는 것을 잊었습니다. 어쨌든 OP의 문제는 수수께끼처럼 보였고 kch의 답변에 대한 힌트를 제외하고는 지금까지 어떤 답변에서도 실제로 해결되지 않았습니다. 그것은 범위의 문제입니다. (편집시 추가 : 실제로 sris의 대답 은 마지막 에이 점을 다루지 만 예제 코드가 문제를 이해하는 데 유용 할 것이라고 생각하므로 어쨌든이 대답을 그대로 두겠습니다 .)
Ruby 클래스에서로 시작하는 변수 이름 @
은 참조 되는 클래스의 위치에 따라 인스턴스 변수 또는 클래스 인스턴스 변수 의 두 변수 중 하나를 참조 할 수 있습니다. 이것은 상당히 미묘한 문제입니다.
예를 들어 요점을 명확히 할 수 있습니다. 다음은 약간의 Ruby 테스트 클래스입니다 (irb에서 테스트 된 모든 코드).
class T
@@class_variable = "BBQ"
@class_instance_variable_1 = "WTF"
@class_instance_variable_2 = "LOL"
def self.class_method
puts "@@class_variable == #{@@class_variable || 'nil'}"
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
def initialize
@instance_variable = "omg"
# The following line does not assign a value to the class instance variable,
# but actually declares an instance variable withthe same name!
@class_instance_variable_1 = "wtf"
puts "@@class_variable == #{@@class_variable || 'nil'}"
# The following two lines do not refer to the class instance variables,
# but to the instance variables with the same names.
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
def instance_method
puts "@@class_variable == #{@@class_variable || 'nil'}"
# The following two lines do not refer to the class instance variables,
# but to the instance variables with the same names.
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
end
항상 그런 것은 아니지만 내가 생각했던대로 변수의 이름을 지정했습니다.
irb> T.class_method
@@class_variable == BBQ
@class_instance_variable_1 == WTF # the value of the class instance variable
@class_instance_variable_2 == LOL # the value of the class instance variable
@instance_variable == nil # does not exist in the class scope
=> nil
irb> t = T.new
@@class_variable == BBQ
@class_instance_variable_1 == wtf # the value of the instance variable
@class_instance_variable_2 == nil # the value of the instance variable
@instance_variable == omg
=> #<T:0x000000015059f0 @instance_variable="omg", @class_instance_variable_1="wtf">
irb> t.instance_method
@@class_variable == BBQ
@class_instance_variable_1 == wtf # the value of the instance variable
@class_instance_variable_2 == nil # the value of the instance variable
@instance_variable == omg
=> nil
irb> T.class_method
@@class_variable == BBQ
@class_instance_variable_1 == WTF # the value of the class instance variable
@class_instance_variable_2 == LOL # the value of the class instance variable
@instance_variable == nil # does not exist in the class scope
=> nil
@@class_variable
와 @instance_variable
항상 당신이 기대하는대로 동작 : 전자는 클래스 레벨에 정의하고, 클래스 메소드 또는 인스턴스 메소드에 언급 여부는 상단에 할당 된 값을 보유하고 있습니다. 후자는 class의 객체에서만 값을 가져 오므로 T
클래스 메서드에서 값이 인 알 수없는 변수를 참조합니다 nil
.
The class method imaginatively named class_method
outputs the values of @@class_variable
and the two @class_instance_variable
s as expected, that is, as initialized at the top of the class. However, in the instance methods initialize
and instance_method
, different variables of the same name are accessed, that is, instance variables, not class instance variables.
You can see that the assignment in the initialize
method did not affect the class instance variable @class_instance_variable_1
, because the later call of class_method
outputs its old value, "WTF"
. Instead, method initialize
declared a new instance variable, one which is also named (misleadingly) @class_instance_variable_1
. The value assigned to it, "wtf"
, is output by methods initialize
and instance_method
.
The variable @class_instance_variable_2
in the example code is equivalent to variable @hello
in the original problem: it's declared and initialized as a class instance variable, but when an instance method refers to a variable of that name, it actually sees an instance variable with the same name -- one which was never declared, so its value is nil.
I'd also recommend looking at class variables which are prefixed with "@@" - here's some sample code to show you how class and instance vars are different:
class Vars
@@classvar="foo"
def test
@instancevar="bar"
end
def Vars.show
puts "classvar: #{@@classvar}"
puts "instancevar: #{@instancevar}"
end
def instance_show
puts "classvar: #{@@classvar}"
puts "instancevar: #{@instancevar}"
end
end
# only shows classvar since we don't have an instance created
Vars::show
# create a class instance
vars = Vars.new
# instancevar still doesn't show b/c it hasn't been initialized
vars.instance_show
# initialize instancevar
vars.test
# now instancevar shows up as we expect
vars.instance_show
참고URL : https://stackoverflow.com/questions/826734/when-do-ruby-instance-variables-get-set
'Nice programing' 카테고리의 다른 글
인수 'fn'은 문자열이있는 함수가 아닙니다. (0) | 2020.11.16 |
---|---|
CentOS 6.5 (최종)에서 PHP 업그레이드 (0) | 2020.11.16 |
C ++에서 최소 및 최대 함수 사용 (0) | 2020.11.16 |
Android : 패턴에서 배경을 만드는 방법은 무엇입니까? (0) | 2020.11.16 |
C99 전 처리기 Turing이 완료 되었습니까? (0) | 2020.11.16 |