Комментарии 15
Отличная статья, не знал про hook методы.
-1
Это называется «полиморфизмом», зачем выдумывать дополнительную терминологию?
+3
А я то все думал, что совсем отстал от жизни — про паттерны знать ничего не знаю, а оно вот в чем дело.
Как всегда, круче всех тот, кто придумает новый модный термин для старых всем известных подходов или технологий.
Я думал это просто переопределение свойств/методов класса, а оно оказывается «Hook методы». Эвона как… :)
Прошу автора не обижаться. Мое бурчание скорее адресовано общемировым тенденциям в IT
Как всегда, круче всех тот, кто придумает новый модный термин для старых всем известных подходов или технологий.
Я думал это просто переопределение свойств/методов класса, а оно оказывается «Hook методы». Эвона как… :)
Прошу автора не обижаться. Мое бурчание скорее адресовано общемировым тенденциям в IT
+2
Мне кажется паттерны проектирования как раз таки и придуманы для того чтобы показать какие есть шаблонные подходы по применению наследования, инкапсуляции и полиморфизма.
0
Как раз сейчас читаю Design Patterns in Ruby, там и про шаблоны и про все! Советую!
0
Автор книги в теме про паттерны, но не очень хорошо оперирует Ruby.
def Wall length, width, material
Module.new do
define_method(:length) { length }
define_method(:width) { width }
define_method(:material) { material }
end
end
class BaseWall
def dimensions
"I am #{length}ft. long and #{width}ft. wide!"
end
def made_from
"I am made from #{material}!"
end
end
class BrickWall < BaseWall
include Wall(30, 20, 'brick')
end
class ConcreteWall < BaseWall
include Wall(30, 20, 'concrete')
end
class WoodWall < BaseWall
include Wall(10, 20, 'wood')
end
-1
Не очень понятно, не могли бы вы пояснить свою реплику и прокомментировать этот кусок кода?
0
С удовольствием.
В верхнем блоке кода мы пользуемся недоступным в большинстве других языков метапрограммированием, являющимся одним из ключевых преимуществ Ruby. Мы делаем шаблон для
Включая (
Остальное вроде бы как в примере из той книги, наследование от BaseWall, определяющего общие для всех стен методы (
Из недостатков вижу то, что метод Wall определён в глобальном контексте, но это легко исправляется переносом его в BaseWall статическим методом.
Второй недостаток — в отличие от примера из книги методы
Итого с этими двумя модификациями:
В верхнем блоке кода мы пользуемся недоступным в большинстве других языков метапрограммированием, являющимся одним из ключевых преимуществ Ruby. Мы делаем шаблон для
Module
, позволяя создавать его на лету. Wall
, как следует из предшествующего перед ним def
— это метод, который определяется в глобальном контексте, возвращающий объект типа Module
с тремя заданными параметрами. Обычно методам принято давать имена со сточной буквы, но в данном случае, для красоты, Wall
идёт с прописной. Для пущей красоты, кстати, можно этот метод положить в BaseWall, сделав его статическим (def self.Wall ...
). Следующие два блока кода эквивалентны: WoodWallModule = Wall(10, 20, 'wood')
module WoodWallModule
def length
10
end
def width
20
end
def material
'wood'
end
end
Включая (
include
) «примесь», то есть module в класс, мы можем использовать все заданные в этом module методы, как если бы они были заданы локально.Остальное вроде бы как в примере из той книги, наследование от BaseWall, определяющего общие для всех стен методы (
dimensions
, made_from
), использующие частные (length
, width
, material
).Из недостатков вижу то, что метод Wall определён в глобальном контексте, но это легко исправляется переносом его в BaseWall статическим методом.
Второй недостаток — в отличие от примера из книги методы
length
, width
, material
являются доступными, public
для объектов стен. Хотя и не указано обратное, но будем точно следовать поведению кода из книги. Это слегка подковыристо, но нужно добавить в определение Module.new
статический метод included
, который вызывается, когда этот module включают (примешивают) в какой-то класс, и установить видимость тех методов, которые мы хотим скрыть в private
: def self.included clazz
private :length, :width, :material
end
Итого с этими двумя модификациями:
class BaseWall
def self.Wall length, width, material
Module.new do
define_method(:length) { length }
define_method(:width) { width }
define_method(:material) { material }
def self.included clazz
private :length, :width, :material
end
end
end
def dimensions
"I am #{length}ft. long and #{width}ft. wide!"
end
def made_from
"I am made from #{material}!"
end
end
class BrickWall < BaseWall
include Wall(30, 20, 'brick')
end
class ConcreteWall < BaseWall
include Wall(30, 20, 'concrete')
end
class WoodWall < BaseWall
include Wall(10, 20, 'wood')
end
0
Если у вас вызывает трудности чтение этого кода, вам нужно начать читать why_'s Poignant Guide to Ruby, а не Design Patterns. Ну или как минимум Objects on Rails от Avdi Grimm.
Моя реплика же судит ужасный код автора книги, который написан на Java, но с синтаксисом Ruby.
Моя реплика же судит ужасный код автора книги, который написан на Java, но с синтаксисом Ruby.
0
То, что в Ruby можно так делать, не значит, что так делать нужно или хорошо в данном случае. Оригинальную статью писал не автор книги. Собственно, в книге пример чуть более комплексный. Для него такой способ не подойдёт.
0
Оценку можно произвести, если определиться с набором аспектов, по которой она идёт. Здесь выбирал читаемость, краткость и возможность повторного использования. Если вы видите какие-то недостатки, или они могут быть выявлены с более комплексном примере — можно посмотреть и на него. Я так понимаю, что это тема как раз для следующего топика топикстартера.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Паттерны проектирования в Ruby: Шаблонный метод