Использование символов Ruby
Впервые я пробовал изучать Ruby было 2 года назад, теперь я снова начал. Причина, по которой я остановилась, состояла в том, что я не мог понять класс Symbol. И теперь я снова нахожусь в том же пункте, полностью потеряв, когда и почему вы используете Символы. Я прочитал другие сообщения в Stackoverflow, а также Googled для нескольких объяснений. Но я пока этого не понимаю.
Сначала я думал, что символы - это просто способ создать какую-то "именованную константу" без необходимости проходить через тот же процесс, что и в Java.
:all
вместо создания константы с произвольным значением public static final String ALL = 8;
Однако это не имеет большого смысла, когда вы используете его, например. attr_accessor :first_name etc.
Являются ли Символы просто легким классом String? У меня возникают проблемы с пониманием того, как я должен интерпретировать, когда и как использовать символы как в моих собственных классах, так и в рамках.
Ответы
Ответ 1
Короче говоря, символы - это легкие строки, но они также являются неизменяемыми и не подлежащими сборке мусора.
Вы должны не использовать их в качестве неизменяемых строк в задачах обработки данных (помните, что после создания символа он не может быть уничтожен). Обычно вы используете символы для обозначения вещей.
# typical use cases
# access hash value
user = User.find(params[:id])
# name something
attr_accessor :first_name
# set hash value in opts parameter
db.collection.update(query, update, multi: true, upsert: true)
Пусть возьмем первый пример, params[:id]
. В приложении с умеренно большим рельсом могут быть сотни/тысячи тех, кто разбросаны по кодовой базе. Если мы обратились к этому значению со строкой, params["id"]
, это означает, что каждый раз назначается новое строковое значение (и эта строка должна быть собрана впоследствии). В случае символа это фактически тот же самый символ везде. Меньшая работа для распределителя памяти, сборщика мусора и даже вы (:
быстрее набирать, чем ""
)
Если у вас есть простая строка с одним словом, которая часто появляется в вашем коде, и вы не делаете с ней что-то смешное (интерполяция, gsub, upcase и т.д.), то скорее всего хорошим кандидатом будет символ.
Однако применимо ли это только к тексту, который используется как часть фактической программной логики, такой как именование, а не текст, который вы получаете при фактическом запуске программы... например, текст от пользователя/веб и т.д.?
Я не могу придумать ни одного случая, когда я хотел бы повернуть данные от пользователя/веб к символу (за исключением, например, синтаксического анализа параметров командной строки). Главным образом из-за последствий (когда созданные символы живут вечно).
Кроме того, многие редакторы предоставляют разные цвета для символов, чтобы выделить их в коде. Взгляните на этот пример
![symbol vs string]()
Ответ 2
В книге "О'Рейли Руби" (стр. 15) цитирует Джима Вейриха:
- Если содержание (последовательность символов) объекта важно, используйте строку.
- Если идентификация объекта важна, используйте символ.
Символы обычно используются в качестве хеш-ключей, потому что они важны для ключевого слова. Символы также необходимы при передаче сообщений с использованием определенных методов, таких как Объект # send.
Ответ 3
Реализация Ruby обычно имеет таблицу, в которой хранятся имена всех классов, методов и переменных. Это означает, что имя метода определяется положением в таблице, избегая дорогостоящих сравнений строк. Но вы также можете использовать эту таблицу и добавить к ней значения: symbols
.
Если вы пишете код, который использует строки как идентификаторы, а не их текстовое содержимое, рассмотрите символы. Если вы напишете метод, который ожидает, что аргумент будет либо "мужским", либо "женским", рассмотрите возможность использования :male
и :female
. Сравнение двух символов для равенства быстрее, чем строк (поэтому символы делают хорошие хэш-ключи).
Ответ 4
Символы используются для обозначения вещей на языке: имена классов, имена методов и т.д.
Они очень похожи на строки, за исключением того, что они никогда не могут быть собраны в мусор, а тестирование на равенство оптимизировано очень быстро.
Реализация Java имеет очень схожую вещь, за исключением того, что она недоступна для использования во время выполнения. Я имею в виду, когда вы пишете Java-код типа obj.someMethod(4)
, строка 'someMethod' преобразуется компилятором в символ, встроенный в таблицу поиска в файле .class. Эти символы похожи на "специальные" строки, которые не собираются в мусор, и которые очень быстро сравниваются для равенства. Это почти идентично Ruby, за исключением того, что Ruby позволяет создавать новые символы во время выполнения, тогда как Java разрешает его во время компиляции.
Это похоже на создание новых методов - Java позволяет это во время компиляции; Ruby позволяет это во время выполнения.