Co oznacza @ @ zmienna w Rubim?
Jakie są zmienne Ruby poprzedzone znakiem double at (@@
)? Moje zrozumienie zmiennej poprzedzonej znakiem at jest takie, że jest to zmienna instancyjna, jak to w PHP:
Wersja PHP
class Person {
public $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
Odpowiednik Ruby
class Person
def set_name(name)
@name = name
end
def get_name()
@name
end
end
Co oznacza podwójny znak at @@
i czym się różni od pojedynczego znaku at?
5 answers
Zmienna z prefiksem @
jest zmienną instancji , podczas gdy jedna z prefiksów @@
jest zmienną klasy . Zobacz poniższy przykład; jego wynik jest w komentarzach na końcu linii 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
Widać, że @@shared
jest współdzielone między klasami; ustawienie wartości w instancji one zmienia wartość dla wszystkich innych instancji tej klasy, a nawet klas potomnych, gdzie zmienna o nazwie @shared
, z jednym @
, nie będzie be.
[Update]
Jak wspomina Phrogz w komentarzach, jest to wspólny idiom w Rubim do śledzenia danych na poziomie klasy za pomocą zmiennej instancji na samej klasie. Może to być trudny temat do ogarnięcia i jest mnóstwo dodatkowego czytania na ten temat, ale pomyśl o tym jako o modyfikacji Class
klasy, ale tylko instancja Class
klasy, z którą pracujesz. Przykład:
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
I included the Square
przykład (który wyprowadza nil
), aby wykazać, że może to nie zachowywać się w 100% tak, jak się spodziewasz; Artykuł, który podlinkowałem powyżej , zawiera mnóstwo dodatkowych informacji na ten temat.
Należy również pamiętać, że tak jak w przypadku większości danych, należy bardzo uważać na zmienne klasy w środowisku wielowątkowym , zgodnie z komentarzem dmarkowa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-05 04:22:19
@
- zmienna instancji klasy@@
- zmienna klasy, nazywana również zmienną statyczną w niektórych przypadkach
Zmienna klasy jest zmienną współdzieloną między wszystkimi instancjami klasy. Oznacza to, że dla wszystkich obiektów utworzonych z tej klasy istnieje tylko jedna wartość zmiennej. Jeśli jedna instancja obiektu zmieni wartość zmiennej, ta nowa wartość zasadniczo zmieni się dla wszystkich innych instancji obiektu.
Innym sposobem myślenia o zmiennych klasowych jest jako zmienne globalne w kontekście jednej klasy.
Zmienne klasy są deklarowane przez prefiks nazwy zmiennej z dwoma znakami @
(@@
). Zmienne klasy muszą być zainicjalizowane w czasie tworzenia
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-09 11:18:58
@@
oznacza zmienną klasy, tzn. może być dziedziczona.
Oznacza to, że jeśli utworzysz podklasę tej klasy, odziedziczy ona zmienną. Więc jeśli masz klasę Vehicle
ze zmienną klasy @@number_of_wheels
to jeśli utworzysz class Car < Vehicle
to również będzie ona miała zmienną klasy @@number_of_wheels
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-01 03:36:43
@ i @ @ w modułach również działają inaczej, gdy Klasa rozszerza lub zawiera ten moduł.
So given
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
Następnie otrzymujesz wyniki poniżej pokazane jako komentarze
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
Więc użyj @ @ w modułach dla zmiennych, które chcesz wspólne dla wszystkich ich zastosowań, i użyj @ w modułach dla zmiennych, które chcesz oddzielne dla każdego kontekstu użycia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-16 04:01:44
Odpowiedzi są częściowo poprawne, ponieważ @ @ jest zmienną klasy, która jest w hierarchii klasowej, co oznacza, że jest współdzielona przez klasę, jej instancje i jej klasy potomne oraz ich instancje.
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
To wyświetli
#<Person:0x007fa70fa24870>
#<Student:0x007fa70fa24848>
Istnieje więc tylko jedna taka sama zmienna @@dla klas Person, Student I Graduate, a wszystkie metody klas I instancji tych klas odnoszą się do tej samej zmiennej.
Istnieje inny sposób definiowania zmiennej klasy, która jest zdefiniowana na obiekcie klasy (pamiętaj, że każda klasa jest rzeczywiście instancją czegoś, co w rzeczywistości jest klasą klasy, ale jest to inna historia). Używasz notacji @ zamiast@@, ale nie możesz uzyskać dostępu do tych zmiennych z metod instancji. Musisz mieć opakowanie metody klasowej.
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(",")
Tutaj @people jest pojedynczą klasą zamiast hierarchii klas, ponieważ jest to zmienna przechowywana na każdej instancji klasy. To jest wyjście:
#<Student:0x007f8e9d2267e8>,#<Student:0x007f8e9d21ff38>
#<Person:0x007f8e9d226158>,#<Person:0x007f8e9d226608>
#<Graduate:0x007f8e9d21fec0>,#<Graduate:0x007f8e9d21fdf8>
Jedną ważną różnicą jest to, że ty nie można uzyskać dostępu do tych zmiennych klasy (lub zmiennych instancji klasy, które można powiedzieć) bezpośrednio z metod instancji, ponieważ @people w metodzie instancji odnosiłaby się do zmiennej instancji tej konkretnej instancji osoby lub klasy studenta lub absolwenta.
Podczas gdy inne odpowiedzi poprawnie stwierdzają, że @ myvariable (z pojedynczą notacją@) jest zawsze zmienną instancyjną, nie musi to oznaczać, że nie jest to pojedyncza wspólna zmienna dla wszystkich instancji tej klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-04 00:34:32