Ruby: вложенные классы в классах такие же, как вложенные классы в модулях? - PullRequest
3 голосов
/ 01 ноября 2011

В Ruby можно объявить классы как

class A
    class B
    end
end

, а затем создать экземпляр внутреннего класса, например A::B.new.

Имеет ли B какие-то особые отношения с A (как в случае с Java) или A только его пространство имен? Другими словами, является ли вложение класса в классе таким же, как вложение его в модуль?

Ответы [ 4 ]

2 голосов
/ 01 ноября 2011

Это один из тех случаев, когда вам нужно просто запустить irb и попробовать его.

Да, класс может быть определен в другом классе. Поскольку суперкласс класса является модулем (то есть класс расширяет модуль), они могут делать практически все, что может модуль. Заметным исключением является то, что вы не можете include (mixin) класс.

Тем не менее, есть очень мало причин для использования этого шаблона проектирования. Более вероятно, что A и B могут считаться родными братьями. Там нет необходимости произвольно именовать пространство, пока вы не посинете в лицо. Если у вас более 3 уровней, остановитесь и подумайте о рефакторинге.

Лучшим шаблоном дизайна для этого примера может быть:

module Alphabet
  class A; end
  class B; end
end

Для чего-то более сложного, это продолжает хорошо работать, используя Mixins:

module Animals
  class Dog
    include Walking
  end

  module Walking
    # some methods pertaining to the ability to walk
  end
end
1 голос
/ 10 ноября 2014

Да и ... нет.Модуль не может быть создан, в то время как класс может, поэтому есть разница во вложении класса в модуле по сравнению с использованием класса, вложенного в класс.

Например: Вы не можете создать экземпляр объекта Ford здесь (например, Cobra, F-150, Mustang и т. Д.), Потому что вы не можете создать экземпляр модуля.

         `module Ford
            class Engine
              ...
            end
          end`

Но вы можете иметь экземпляр класса Ford, а также экземпляры двигателей Ford с использованием вложенных классов, например:

       `class Ford
           class Engine
             @@actions = ['list', 'find', 'add', 'quit']
             def self.actions; @@actions; end
           end

           def self.truck_exists?
             #Some more stuff here
           end
        end` 
1 голос
/ 01 ноября 2011

Да, это по сути то же самое, что и вложенность в модуль.Вложенный класс не имеет никакого особого отношения к классу, в который он вложен.

0 голосов
/ 01 ноября 2011

Классы (и Модули) имеют различное использование:

  • Пространство имен: когда вы определяете класс (или модуль) внутри другого класса (или модуля), вы должны использовать другую нотацию вне определениякласс для доступа к внутреннему классу или модулю.
  • Шаблон для экземпляров: там модули и классы ведут себя совершенно (в основном) по-разному.
  • Наследование: Вы можете расширять класс, поэтому вы наследуете все егоатрибуты и методы, которые работают и для модулей.Или вы можете включить модуль (не класс), чтобы добавить его методы (и атрибуты) в вашу область видимости.Ruby играет здесь трюки, смешивая модуль в иерархии классов.

Так что в контексте использования пространств имен они одинаковы.Однако я бы все время использовал модули (только), но это больше вопрос стиля.На мой взгляд, лучшая книга на эту тему - "Метапрограммирование Руби" Паоло Перротта.

...