Сначала пара слов о картинке. По запросу «object oriented programming» к гугл.картинкам она отдается на первой странице. Так-то.
Все мы с молоком матери впитали, что «еврибади из обжект», достаточно вспомнить о «
mov ax dx
», который, согласно первым AI, переводится на русский язык как «двинул топором начальника штаба». Тем не менее, иногда хочется стройности. Особенно, когда твоя библиотека переживает очередной git push
, и ты понимаешь, что теперь обязательно найдется кто-нибудь, жаждущий вызвать Divider.new (UndividedObject.new)
.Иными словами, если вам вдруг втемяшилось повторить функциональность OOP Fops, наподобие Java/.NET — это можно. Но, пожалуйста, не нужно так делать. Вызов
.respond_to?
всегда дешевле, понятнее и элегантнее мусора, который я готов вам показать:
module MyModuleSet module MyModule class InterfaceNotImplemented < NoMethodError end def self.included(clazz) clazz.send(:include, MyModule::Methods) clazz.send(:extend, MyModule::Methods) clazz.send(:extend, MyModule::ClassMethods) end module Methods def not_implemented(clazz, method = nil) if method.nil? caller.first.match(/in \`(.+)\'/) method = $1 end raise MyModule::InterfaceNotImplemented.new("#{clazz.class.name} is abstract ('#{method}' must be implemented.)") end end module ClassMethods def to_implement!(name, *args) self.class_eval do define_method(name) do |*args| not_implemented(self, name) end end end end end class AbstractClass include MyModule to_implement! :method1, :method2 … end
Это непотребство бросит исключение, если в наследнике не объявлены method1 и method2. Но.
Я настаиваю на том, что так делать не нужно. Не сто́ит тащить за собой в новую жизнь груз ошибок. Если приходится полагаться на чужой код, всегда лучше написать «respond_to?», чем городить никому не понятный и не нужный огород.
Я написал эту заметку, поскольку сам поддался соблазну сделать что-то подобное. Пусть она отдается в поиске по плохим практикам.
ссылка на оригинал статьи http://habrahabr.ru/post/162557/
Добавить комментарий