Когда использовать модуль и когда использовать класс
В настоящее время я работаю над книгой Gregory Brown Ruby Best Practices. В начале он говорит о реорганизации некоторых функций из вспомогательных методов в связанном классе, с некоторыми методами на модуле, а затем имеет модуль extend self
.
Не видел, что раньше, после быстрого google, выяснилось, что extend self
в модуле позволяет методам, определенным в модуле, видеть друг друга, что имеет смысл.
Теперь, мой вопрос: когда бы вы сделали что-то вроде этого
module StyleParser
extend self
def process(text)
...
end
def style_tag?(text)
...
end
end
а затем обратитесь к нему в тесте
@parser = Prawn::Document::Text::StyleParser
в отличие от чего-то подобного?
class StyleParser
def self.process(text)
...
end
def self.style_tag?(text)
...
end
end
Это так, что вы можете использовать его как mixin? или есть другие причины, которые я не вижу?
Ответы
Ответ 1
Класс должен использоваться для функциональности, которая потребует создания экземпляра или для отслеживания состояния. Модуль может использоваться как способ сочетания функциональности с несколькими классами или как способ предоставления одноразовых функций, которые не нужно создавать или отслеживать состояние. Метод класса также может быть использован для последнего.
Имея это в виду, я считаю, что различие заключается в том, действительно ли вам нужен класс. Метод класса кажется более уместным, если у вас есть существующий класс, который нуждается в некоторых одноэлементных функциях. Если то, что вы делаете, состоит только из однокнопочных методов, имеет смысл реализовать его как модуль и получить доступ к нему через модуль напрямую.
Ответ 2
В этом конкретном случае я, вероятно, не пользовался ни классом, ни модулем.
Класс - это factory для объектов (обратите внимание на множественное число). Если вы не хотите создавать несколько экземпляров класса, нет необходимости в его существовании.
Модуль представляет собой контейнер для методов, разделяемых между несколькими объектами. Если вы не смешиваете модуль в нескольких объектах, нет необходимости в его существовании.
В этом случае похоже, что вы просто хотите объект. Поэтому используйте один:
def (StyleParser = Object.new).process(text)
...
end
def StyleParser.style_tag?(text)
...
end
Или, альтернативно:
class << (StyleParser = Object.new)
def process(text)
...
end
def style_tag?(text)
...
end
end
Но поскольку @Azeem уже писал: для правильного решения вам нужен больше контекста. Я недостаточно хорошо знаком с внутренними силами Кревеца, чтобы узнать, почему Грегори принял это конкретное решение.
Ответ 3
Если это то, что вы хотите создать, используйте класс. Остальная часть вашего вопроса нуждается в большем контексте, чтобы иметь смысл.