Частный класс (не метод класса) в модуле Ruby?

Я плохо знаком с Ruby (опытный с Python, C++ и C). Я должен создать класс, который является только, чтобы использоваться другими классами и методами в модуле. В Python я просто назвал бы его __ имя класса. Я использовал бы пустое определение типа в C++. Как я делаю это в Ruby (или я рявкаю неправильное дерево и не делаю это "Ruby путь"?)

16
задан Mladen Jablanović 16 August 2010 в 20:16
поделиться

2 ответа

Я пока не встречал такой концепции в Ruby, но, думаю, вы можете имитировать это, создав приватный метод, который будет возвращать класс, созданный как локальная переменная (помните, что в Ruby класс - это такой же объект, как и любой другой, и может быть инстанцирован в методе и возвращен им).

BTW, даже приватные методы в Ruby не такие приватные, как в других языках - вы всегда можете получить к ним доступ, используя метод send. Но это подразумевает, что вы знаете, что делаете.

4
ответ дан 30 November 2019 в 16:18
поделиться

Самое важное, что нужно понимать, - это то, что в классе нет ничего особенного. Это просто объект. Согласно соглашению, классы назначаются константам, но ничто не говорит о том, что они должны быть .

А поскольку классы - это просто объекты, как и любой другой объект, вы делаете их частными так же, как и любой другой объект.

Вот возможности, которые я могу придумать, в порядке увеличения приватности:

  1. Просто вложите их в пространство имен (то есть модуль). В Ruby обычно ожидается, что все модули и классы библиотеки находятся в пространстве имен с тем же именем, что и библиотека (например, my_awesome_library MyAwesomeLibrary ), но в целом все который вложен ниже этого пространства имен, считается закрытым. Фактически, помимо Test :: Unit :: TestCase , я не могу придумать ни одного примера трехуровневого глубокого пространства имен, которое, как ожидается, действительно будет использоваться клиентским кодом.
  2. то же, что 1., но назовите что-нибудь очевидное, например MyAwesomeLibrary :: Internal :: FfiStruct
  3. то же самое, что 1. или 2., и отметьте его : nodoc: Тег RDoc.
  4. похож на 3., но использует более современную систему документации, такую ​​как YARD, которая фактически позволяет вам явно размечать частные API.
  5. Используйте метод вместо константы. Методы можно сделать частными.(Для единообразия вы можете начинать имя метода с заглавной буквы, чтобы оно напоминало константу. Ничто не может этому помешать, соглашение snake_case - это всего лишь соглашение.)
  6. Используйте переменную экземпляра. Они всегда конфиденциальны. Обратите внимание, что как частные методы, так и переменные экземпляра могут быть тривиально доступны с помощью отражения. Однако send , похоже, более широко используется, чем instance_variable_get , поэтому я считаю, что переменные экземпляра имеют более высокий уровень конфиденциальности, чем методы.
  7. Однако на самом деле единственный способ получить реальную конфиденциальность или инкапсуляцию - это использовать локальные переменные и замыкания. Однако обратите внимание, что это может помешать вам использовать синтаксис определения модуля, класса или метода Ruby, потому что они создают новые области видимости. Во всех случаях, когда вам нужен доступ к классу, вам необходимо использовать Module.new , Class.new или Module # define_method .

Пример:

module MyAwesomeLibrary
  struct = Class.new(FFI::Struct) do
    # ...
  end

  PublicInterface = Class.new do
    define_method(:initialize) do |bar|
      @foo = struct.new(bar)
    end
  end
end

И да, это единственный способ достижения истинного 100% сокрытия и инкапсуляции информации в Ruby.

Однако нормальный способ Ruby - просто задокументировать материал как частный (возможно, опустить его на уровень пространства имен) и доверять другим разработчикам. В сообществе Ruby это иногда обобщается под лозунгом Python «Мы все взрослые по взаимному согласию».

27
ответ дан 30 November 2019 в 16:18
поделиться