2011-05-04 4 views
126

기호 앞에 double이 붙은 Ruby 변수는 무엇입니까 (@@)? at 기호 앞에는 변수의 나의 이해는 인스턴스 변수가 PHP에서 다음과 같이이다이다 :@@ 변수가 Ruby에서 의미하는 것은 무엇입니까?

PHP 버전에 해당하는

class Person { 

    public $name; 

    public function setName($name) { 
     $this->name = $name; 
    } 

    public function getName() { 
     return $this->name; 
    } 
} 

루비

의 두 배를 무엇
class Person 

    def set_name(name) 
     @name = name 
    end 

    def get_name() 
     @name 
    end 
end 

@@ 기호를 의미하고, 기호 하나의 기호와 어떻게 다른가요?

+77

나는 잘 모르지만, 나는 그것이 나를 쳐다보고 있다고 느낀다. Ruby에서 코드를 작성하는 데 약간 겁이납니다 ... – corsiKa

+0

TL; 공용에 대한 DR : 100 회 중 99 회, 클래스 변수가 아닌 "클래스 인스턴스"변수 ('''''self '메서드 내에서)를 사용합니다. '@@'). 이유에 대한 자세한 내용은 아래의 답변을 참조하십시오. – WattsInABox

답변

188

@@로 시작 하나가를하는 동안 @로 시작 변수가 예 변수입니다 클래스 변수 다음 예제를 확인하십시오. 출력은 puts 라인의 끝 부분에 코멘트에 있습니다

class Test 
    @@shared = 1 

    def value 
    @@shared 
    end 

    def value=(value) 
    @@shared = value 
    end 
end 

class AnotherTest < Test; end 

t = Test.new 
puts "t.value is #{t.value}" # 1 
t.value = 2 
puts "t.value is #{t.value}" # 2 

x = Test.new 
puts "x.value is #{x.value}" # 2 

a = AnotherTest.new 
puts "a.value is #{a.value}" # 2 
a.value = 3 
puts "a.value is #{a.value}" # 3 
puts "t.value is #{t.value}" # 3 
puts "x.value is #{x.value}" # 3 

당신은 @@shared은 클래스간에 공유되는 것을 볼 수 있습니다; 하나의 인스턴스에서 값을 설정하면 해당 클래스의 다른 모든 인스턴스에 대한 값이 변경되고 심지어 @shared이라는 변수가 하나의 @ 인 자식 클래스는 변경되지 않습니다.

[업데이트]

Phrogz이 코멘트에 언급 된 바와 같이, 그것은 클래스 자체에 변수 인스턴스와 클래스 수준의 데이터를 추적하기 위해 루비의 일반적인 관용구이다. 주제를 다룰 때 까다로운 주제 일 수 있으며 주제에 이 많이 있지만, Class 클래스를 수정하는 것으로 생각하면 Class 클래스의 인스턴스 만 사용하십시오. 예 :

class Polygon 
    class << self 
    attr_accessor :sides 
    end 
end 

class Triangle < Polygon 
    @sides = 3 
end 

class Rectangle < Polygon 
    @sides = 4 
end 

class Square < Rectangle 
end 

class Hexagon < Polygon 
    @sides = 6 
end 

puts "Triangle.sides: #{Triangle.sides.inspect}" # 3 
puts "Rectangle.sides: #{Rectangle.sides.inspect}" # 4 
puts "Square.sides: #{Square.sides.inspect}" # nil 
puts "Hexagon.sides: #{Hexagon.sides.inspect}" # 6 

나는 예상대로이 100 % 작동하지 않을 수 있다는 것을 보여주기 위해 (nil를 출력)를 Square 예를 포함; article I linked above에는 주제에 대한 많은 추가 정보가 있습니다.

또한 대부분의 데이터와 마찬가지로 dmarkow의 설명에 따라 클래스 변수를 multithreaded environment에 매우주의해야합니다.

+1

이 대답은 클래스 레벨에서 인스턴스 변수를 사용하여 하위 클래스간에 데이터를 공유하는 '이상한'동작없이 클래스 수준의 데이터를 추적하는 방법을 보여주는 코드가 포함 된 경우 완벽한 IMHO가됩니다. – Phrogz

+2

또한 클래스 변수가 멀티 스레드 환경 (예 : 레일즈)에서 위험하거나 신뢰할 수 없다는 점을 지적하고자합니다. –

+0

흠 ... PHP에서는 정적 변수처럼 들리지만 상속 부분은 다릅니다. 나는 PHP가 이와 비슷한 것을 가지고 있다고 생각하지 않는다. – Andrew

9

@@은 클래스 변수를 나타내며, 즉 상속 될 수 있습니다.

즉, 해당 클래스의 하위 클래스를 만들면 해당 변수가 상속됩니다. 당신은 클래스와 클래스 Vehicle이있는 경우 그럼 @@number_of_wheels 변수 당신은 class Car < Vehicle 다음 너무 변수 클래스가됩니다 만들 경우 @@number_of_wheels

+0

그게 무슨 뜻입니까? – Andrew

+0

즉, 해당 클래스의 하위 클래스를 만들면 변수를 상속받습니다. 클래스 변수'@@ number_of_wheels'를 가진'Vehicle' 클래스가 있다면'클래스 자동차

+12

클래스 차량 '를'@ number_of_wheels'로 설정하면'class Car

32

@ - 클래스의 인스턴스 변수
@@ - 또한 어떤 경우

클래스 변수에 정적 변수로 불리는 클래스 변수, 클래스의 모든 인스턴스 사이에 공유되는 변수입니다. 즉,이 클래스에서 인스턴스화 된 모든 객체에 대해 하나의 변수 값만 존재합니다.하나의 객체 인스턴스가 변수의 값을 변경하면, 그 새로운 값은 다른 모든 객체 인스턴스에 대해 필수적으로 변경됩니다.

클래스 변수를 생각하는 또 다른 방법은 단일 클래스의 컨텍스트 내에서 전역 변수입니다. 클래스 변수 앞에 변수 이름 접두사 @ (@@)을 두어 선언합니다. 클래스 변수를 생성시 초기화되어야

0

@ = 인스턴스 변수 여기서 같은 @@ = 변수 클래스

인스턴스 변수가처럼 공유 인스턴스 인 /를 액세스하기 위해 클래스 물체 우리가 그 인스턴스 변수에 대한 setter와 getter를 정의 할 필요가있는 인스턴스 변수

클래스 변수는 비슷합니다. 이것은 클래스 의 모든 인스턴스/객체간에 공유됩니다. 즉, 그것이 전역 변수라고 말할 수 있습니다. 변수이므로 전역 변수에 전역으로 액세스 할 수 있습니다.

0

@ 및 @@ 모듈도 클래스가 모듈을 확장하거나 포함 할 때 다르게 작동합니다.

은 그래서 같이 아래

class X 
    extend A 

    puts get1.inspect # nil 
    puts get2.inspect # "module" 

    @a = 'class' 
    @@a = 'class' 

    puts get1.inspect # "class" 
    puts get2.inspect # "module" 

    set1('set') 
    set2('set') 

    puts get1.inspect # "set" 
    puts get2.inspect # "set" 

    A.set1('sset') 
    A.set2('sset') 

    puts get1.inspect # "set" 
    puts get2.inspect # "sset" 
end 

class Y 
    include A 

    def doit 
     puts get1.inspect # nil 
     puts get2.inspect # "module" 

     @a = 'class' 
     @@a = 'class' 

     puts get1.inspect # "class" 
     puts get2.inspect # "class" 

     set1('set') 
     set2('set') 

     puts get1.inspect # "set" 
     puts get2.inspect # "set" 

     A.set1('sset') 
     A.set2('sset') 

     puts get1.inspect # "set" 
     puts get2.inspect # "sset" 
    end 
end 

Y.new.doit 

그래서 당신이 모든 용도에 공통적으로 원하는 변수 모듈 @@ 사용 코멘트대로 출력을 얻을 다음

module A 
    @a = 'module' 
    @@a = 'module' 

    def get1 
     @a   
    end  

    def get2 
     @@a   
    end  

    def set1(a) 
     @a = a  
    end  

    def set2(a) 
     @@a = a  
    end  

    def self.set1(a) 
     @a = a  
    end  

    def self.set2(a) 
     @@a = a  
    end  
end 

을 부여하고, 모듈에서 사용 @ 변수는 모든 사용 컨텍스트에 대해 분리해야합니다.

관련 문제