2012-06-25 3 views
0

루비가 인스턴스 변수 대신 로컬 변수 안에 이러한 클래스를 인스턴스화/저장하는 이유는 무엇입니까?루비가 인스턴스 변수 대신 로컬 변수를 내부에 저장하고 있습니다

나는 그것이 작동하도록하려면 코드를 변경하기 전에,이 있었다 :

% ruby -I. converter_test.rb             ✭ 
Run options: 

# Running tests: 

EE 

Finished tests in 0.000616s, 3246.7638 tests/s, 0.0000 assertions/s. 

    1) Error: 
test_celsius(TestConverter): 
NoMethodError: undefined method `celsius' for nil:NilClass 
    converter_test.rb:9:in `test_celsius' 

    2) Error: 
test_fahrenheit(TestConverter): 
NoMethodError: undefined method `fahrenheit' for nil:NilClass 
    converter_test.rb:14:in `test_fahrenheit' 

2 tests, 0 assertions, 0 failures, 2 errors, 0 skips 

내가 각각의 내부 클래스 (변환)을 인스턴스화하기로 결정이 오류가 발생했습니다

require 'test/unit' 
require 'converter' 

class TestConverter < Test::Unit::TestCase 

    @cv = Convert.new 

    def test_celsius 
    assert_equal(100.0, @cv.celsius(212)) 
    assert_equal(0.0, @[email protected](32)) 
    end 

    def test_fahrenheit 
    assert_equal(212.0, @cv.fahrenheit(100)) 
    assert_equal(32.0, @cv.fahrenheit(0)) 
    end 

end 

메소드가 성공하여 성공했습니다 :

require 'test/unit' 
require 'converter' 

class TestConverter < Test::Unit::TestCase 

    #@cv = Convert.new 
    #instantiated the class in each method instead of here 

    def test_celsius 
    cv = Convert.new 
    assert_equal(100.0, cv.celsius(212)) 
    assert_equal(0, cv.celsius(32)) 
    end 

    def test_fahrenheit 
    cv = Convert.new 
    assert_equal(212, cv.fahrenheit(100)) 
assert_equal(32, cv.fahrenheit(0)) 
end 
end 
[email protected]:~/Develop/davincicoders$ ruby -I. converter_test.rb 
Run options: 

# Running tests: 

.. 

Finished tests in 0.001894s, 1055.9149 tests/s, 2111.8298 assertions/s. 

2 tests, 4 assertions, 0 failures, 0 errors, 0 skips 

왜 Ruby는 인스턴스 변수를 다음과 같이 인식하지 않습니까? 첫 번째 시도의 객체?

+0

Ruby에서 인스턴스 변수를 선언하는 방식이 아니기 때문입니다. 클래스 선언에서는 인스턴스가 아니라 클래스에 있으므로 @ 변수는 자신이 생각하는 것이 아닙니다. –

+1

그래서 기본적으로 메소드의 인스턴스 외부를 정의했기 때문에 작동하지 않았습니다. 초기화 방법의 내부에서 작업을 수행했다면 작동했을 것입니다. 권리? 음 ... 테스트의 내부에서 이것이 작동하지 않는 것처럼 보입니다 ... 좋아요, 생각합니다. 고마워. –

+0

가장 효율적인 코드는 무엇입니까? @@ class_var 선언을 사용하거나 위에서 수행 한 방식대로 수행합니까? –

답변

3

@cv 수 없을 겁니다 그것을 TestConverter에 대한 인스턴스 변수 -하지 TestConverter의 인스턴스!

아마도이 문제를 해결하는 가장 쉬운 방법은 클래스 변수 인 @@cv이 될 것입니다.

여전히 혼동하는 경우,이 예제를 고려 : 당신이 다른 언어에서 기대할 수있는 것보다 다르게 작동하기 때문에 (나를 포함한) 사람들에게

class Foo 
    @x = 3 
    def initialize 
    @y = 4 
    end 
end 

puts Foo.instance_variables 
puts Foo.new.instance_variables 
+0

허. 나는 이것을 명상 할 것이다. –

0
assert_equal(0.0, @[email protected](32)) 

이 테스트 외부

선언
assert_equal(0.0, @cv.celsius(32)) 
+0

예, 실제로 인스턴스 변수 인 경우 ...하지만 OP가 믿는 것의 인스턴스 변수가 아닙니다. 궁극적으로 이것은 Ruby에 대한 오해 인 실제 질문에 대답하지 않습니다. –

+0

OP는 무엇입니까? –

+0

@David "OP"는 "Original Poster"를 의미합니다. 그것은 섹스에 독립적이며 질문하는 사람을 지칭하는 짧은 길입니다. – Phrogz

2

이 종종 혼동된다. 나는 자바 예제를 설명하려고합니다 :

class Foo 
    @bar = 42 
end 

public class Foo { 
     private static int bar = 42; 
} 

당신의 IRB에 그것을 밖으로 시도 거의 비슷 실제로 하지 해당

public class Foo { 
     private int bar = 42; 
} 

에 불과하다 :

class Foo 
    attr_accessor :bar 
    @bar = 42 
    class << self 
    attr_accessor :bar 
    end 
end 
Foo.bar # => 42 
Foo.new.bar # => nil 

왜 그렇습니까? 루비에서는 모든 것이 객체입니다! 따라서 모든 클래스 (예 : Foo)는 Class 클래스의 인스턴스입니다 (혼란스러운 소리입니다.) class Foo; end 사이의 내용은 Class 클래스 Foo 인스턴스의 범위에서 실행됩니다.

이것은 완전한 설명이 아니므로 세부 정보를 정말로 읽어야합니다.