Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
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
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 методы, как если бы они были заданы локально.dimensions, made_from), использующие частные (length, width, material).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
Паттерны проектирования в Ruby: Шаблонный метод