2014-07-24 13 views
9

Próbuję zrozumieć, jaka jest różnica między symbolem a zmienną w rubinie. Wydawali się robić dokładnie to samo, podając imię, które odnosi się do przedmiotu.Jaka jest różnica między symbolem a zmienną w Ruby?

Przeczytałem, że symbole umożliwiają szybsze programy, ale nie jestem pewien, dlaczego i jak one różnią się od zmiennych w jakikolwiek sposób.

+0

Zobacz także "[Co to jest operator dwukropka w Rubim?] (Http://stackoverflow.com/questions/6337897/what-is-the-colon-operator-in-ruby)". –

Odpowiedz

11

Symbol jest "zinternalizowanym" łańcuchem, bardziej przypomina stałą niż cokolwiek innego. Typowy przykład:

account_details = { 
    :name => 'Bob', 
    :age => 20 
} 

tutaj symbole :name i :age są kluczami do mieszania. Nie należy ich mylić ze zmiennymi. account_details jest zmienną.

Zmienna w Ruby to uchwyt do pewnego rodzaju obiektu, który może być symbolem.

Zwykle podczas używania ciągów używa się symboli, co spowodowałoby wiele powtórzeń. Należy pamiętać, że łańcuchy są zwykle odrębnymi obiektami, w których odrębny symbol zawsze odnosi się do tego samego obiektu, dzięki czemu są bardziej wydajne, jeśli są często używane.

Porównaj:

"string".object_id == "string".object_id 
# => false 

:string.object_id == :string.object_id 
# => true 

Nawet jeśli te dwa ciągi są identyczne, są one niezależne obiekty ciągów. Kiedy są używane jako klucze dla skrótów, argumentów dla metod i innych typowych przypadków, obiekty te szybko zapełnią twoją pamięć masowymi ilościami duplikacji, chyba że zechcesz użyć tej samej instancji łańcucha. Symbole robią to automatycznie.

+0

Dzięki za odpowiedź, myślę, że moje zamieszanie pochodzi z użycia symboli z atrybutami. Podczas pisania czytnika atrybutów dla zmiennej instancji w atrybucie używany jest symbol, ale zwracana jest zmienna. W jaki sposób symbol odnosi się do zmiennej instancji w tym przypadku? – Cu1ture

+2

'attr_accessor: example' oznacza" zdefiniuj atrybut odczytu/zapisu o nazwie 'example' "i definiuje metodę' example' oraz example = 'oraz zmienną instancji' @ example'. Argument jest przekazywany jako symbol, więc metoda odbierająca może powiedzieć, co to jest. Pamiętaj, że nazwy zmiennych są lokalne, nazwa zmiennej nigdy nie jest przekazywana. "Przykład attr_reader" oznacza "utwórz czytnik z dowolną zmienną * przykładową *, która chce ją nazwać". Funkcja 'attr_reader' nie ma możliwości poznania nazwy zmiennej. Związek tutaj jest symbolem jest używany do komunikowania pożądanej nazwy. – tadman

4

Są całkiem różne. Zmienne nadają etykietę obiektowi. Symbole są bardziej podobne do łańcuchów, z tym wyjątkiem, że są niezmienne i internowane w pamięci, tak że wiele odniesień do tego samego symbolu nie używa dodatkowej pamięci. (Porównaj to z ciągami, w których wiele odwołań do tego samego ciągu znaków spowoduje wielokrotne skopiowanie ciągu znaków.)

+0

Czy odwołanie do łańcucha za pomocą zmiennej nie robi tego samego i zachowuje jedno wystąpienie w pamięci? To samo, co użycie zmiennych w JS, aby zapobiec duplikacji i uzyskać tylko te same dane raz. – Cameron

+0

@Cameron: Cóż, w przypadku czegoś takiego jak "a =" ciąg ", b = a", tak. W przypadku ciągu "a =" "; b = "string" ', zostaną utworzone dwa obiekty z zawartością" string ". (Nie jestem pewien, jak JS to obsługuje.) – mipadi

5

Zmienne przechowują odwołanie do obiektu. Na przykład, zmienne mogą wskazywać na łańcuchy i symbole, takie jak:

a = 'foo' 
b = :bar 

W Ruby ciąg są zmienne, to znaczy, że można je zmienić: 'foo' + 'bar' da łączone ciąg. Możesz postrzegać symbole jako niezmienne ciągi, co oznacza, że ​​nie możesz zmienić symbolu: :foo + :bar spowoduje błąd. Co najważniejsze, te same symbole odnoszą się do tego samego obiektu:

a = :foo 
b = :foo 
a.object_id # => 538728 
b.object_id # => 538728 

Zwiększa to wydajność wyszukiwania hash i innych operacji.

+1

Chciałbym zwrócić uwagę przyszłych czytelników, że możliwość dodania dwóch obiektów w celu uzyskania innego obiektu nie oznacza, że ​​obiekt jest zmienny. Struny w Pythonie i Lua są niezmienne; dodanie dwóch z nich daje ci inny obiekt. W Ruby łańcuchy są zmienne, ale dodanie dwóch z nich nie zmienia żadnego z łańcuchów bazowych, daje nowy obiekt typu string. – Taywee