
Сначала пара слов о картинке. По запросу «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/
Добавить комментарий