이중 변수 ( @@
) 앞에 Ruby 변수가 무엇입니까 ? at 기호가 앞에 오는 변수에 대한 이해는 PHP에서 다음과 같은 인스턴스 변수라는 것입니다.
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
이중 부호는 무엇을 @@
의미하며 단일 부호와 어떻게 다른가요?
답변
접두사가 붙은 변수 @
는 인스턴스 변수 이고 접두사가 붙은 변수@@
는 클래스 변수 입니다. 다음 예를 확인하십시오. 출력은 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가 주석에서 언급했듯이 Ruby 자체는 클래스 자체 의 인스턴스 변수로 클래스 레벨 데이터를 추적하는 일반적인 관용구입니다 . 이것은 당신의 마음을 감싸기가 까다로운 주제 일 수 있으며, 주제 에 대한 추가 자료 가 많이 있지만 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 % 동작하지 않을 수 있음을 보여주는 Square
예제 (출력 nil
)를 포함 시켰습니다 . 제가 위에 링크 된 문서 주제에 대한 추가 정보를 많이 가지고있다.
또한 대부분의 데이터와 마찬가지로 dmarkow의 의견 에 따라 다중 스레드 환경 에서 클래스 변수에 매우주의해야합니다 .
답변
@
-클래스의 인스턴스 변수
@@
-클래스 변수, 경우에 따라 정적 변수라고도 함
클래스 변수는 클래스의 모든 인스턴스간에 공유되는 변수입니다. 이는이 클래스에서 인스턴스화 된 모든 객체에 대해 하나의 변수 값만 존재 함을 의미합니다. 하나의 객체 인스턴스가 변수의 값을 변경하면 해당 값은 다른 모든 객체 인스턴스에 대해 본질적으로 변경됩니다.
클래스 변수를 생각하는 또 다른 방법은 단일 클래스의 맥락에서 전역 변수입니다. 클래스 변수는 변수 이름 앞에 두 @
문자 ( @@
)를 붙여 선언합니다 . 생성시 클래스 변수를 초기화해야합니다
답변
@@
클래스 변수를 나타냅니다. 즉, 상속 될 수 있습니다.
즉, 해당 클래스의 하위 클래스를 만들면 변수가 상속됩니다. 따라서 Vehicle
클래스 변수 가있는 클래스 가 @@number_of_wheels
있다면 클래스 변수 를 생성 class Car < Vehicle
하면 클래스 변수도 갖게됩니다@@number_of_wheels
답변
클래스의 @ 및 @@는 클래스가 해당 모듈을 확장하거나 포함 할 때 다르게 작동합니다.
그래서 주어진
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
그런 다음 아래 출력을 주석으로 표시합니다.
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
따라서 모든 용도에 공통적으로 사용되는 변수에 대해 모듈에서 @@을 사용하고 모든 사용 컨텍스트에 대해 별도의 변수에 대해 모듈에서 @@를 사용하십시오.
답변
@@는 실제로 클래스 계층 당 클래스 변수이므로 클래스, 해당 인스턴스 및 해당 하위 클래스 및 해당 인스턴스가 공유한다는 의미이므로 부분적으로 정확합니다.
class Person
@@people = []
def initialize
@@people << self
end
def self.people
@@people
end
end
class Student < Person
end
class Graduate < Student
end
Person.new
Student.new
puts Graduate.people
출력됩니다
#<Person:0x007fa70fa24870>
#<Student:0x007fa70fa24848>
따라서 Person, Student 및 Graduate 클래스에 대해 동일한 @@ variable이 하나만 있으며 이러한 클래스의 모든 클래스 및 인스턴스 메소드는 동일한 변수를 참조합니다.
클래스 객체에 정의 된 클래스 변수를 정의하는 또 다른 방법이 있습니다 (각 클래스는 실제로는 실제로 클래스 클래스이지만 다른 이야기 임). @@ 대신 @ 표기법을 사용하지만 인스턴스 메소드에서 이러한 변수에 액세스 할 수 없습니다. 클래스 메소드 랩퍼가 있어야합니다.
class Person
def initialize
self.class.add_person self
end
def self.people
@people
end
def self.add_person instance
@people ||= []
@people << instance
end
end
class Student < Person
end
class Graduate < Student
end
Person.new
Person.new
Student.new
Student.new
Graduate.new
Graduate.new
puts Student.people.join(",")
puts Person.people.join(",")
puts Graduate.people.join(",")
여기서 @people은 실제로 각 클래스 인스턴스에 저장된 변수이기 때문에 클래스 계층 구조 대신 클래스 당 단일입니다. 이것은 출력입니다.
#<Student:0x007f8e9d2267e8>,#<Student:0x007f8e9d21ff38>
#<Person:0x007f8e9d226158>,#<Person:0x007f8e9d226608>
#<Graduate:0x007f8e9d21fec0>,#<Graduate:0x007f8e9d21fdf8>
한 가지 중요한 차이점은 인스턴스 메소드의 @people가 Person 또는 Student 또는 Graduate 클래스의 특정 인스턴스의 인스턴스 변수를 참조하기 때문에 인스턴스 메소드에서 직접 이러한 클래스 변수 (또는 말할 수있는 클래스 인스턴스 변수)에 액세스 할 수 없다는 것입니다 .
따라서 다른 답변에 @myvariable (단일 @ 표기법 사용)이 항상 인스턴스 변수라고 명시되어 있지만 반드시 해당 클래스의 모든 인스턴스에 대해 단일 공유 변수가 아님을 의미하지는 않습니다.