Comments 40
разве MixIn не из этой области?
Mixin это всего лишь набор методов, так скажем. Вопрос в том как его включить для работы в нужные классы. В ruby вы можете его подключить во встроенные классы, благодаря их открытости.
Всю жизнь знаю, что mixin — это способ внесения изменений в классы, без наследования.
Не точно, но кажется нельзя подмешивать что-либо в классы int и str (и прочие builtin-классы, которые немного не такие), но во все остальные — никаких проблем.
Не точно, но кажется нельзя подмешивать что-либо в классы int и str (и прочие builtin-классы, которые немного не такие), но во все остальные — никаких проблем.
Эм, почему «В python нельзя определить новые методы для сторонних классов»?
А вообще, ковыряться во внутренностях того, с чем надо взаимодействовать как с «чёрным ящиком» — плохая идея.
class A(object):
pass
a = A()
def new_method(self):
print "It's working!"
setattr(A, 'new_method', new_method)
a.new_method()
А вообще, ковыряться во внутренностях того, с чем надо взаимодействовать как с «чёрным ящиком» — плохая идея.
Я не говорил о принципиальной невозможности, просто так не делается. Да и setattr здесь лишний, можете просто присвоить.
И потом я об открытых классах ruby, а не о системе типов python.
>>> A.kuku = new_method
>>> a.kuku()
It's working!
И потом я об открытых классах ruby, а не о системе типов python.
setattr
не лишний, он абстрактнее простого присвоения.Помню, переносил как-то Ruby-библиотеку с одной версии языка на другую. Тем, что с новым Ruby всё вдруг поламалось, наверное, никого не удивишь. Но вот зато какое «удовольствие» было искать, где же всё-таки определён один такой перегруженный метод! Нужно знать не только, в каком файле он прописан, но и в какой последовательности загружаются модули. А это значит, что чтобы понять какую-то маленькую деталь, нужно сначала осознать поток контроля во всём приложении, что довольно сложно без понимания вот таких деталей.
А пример неудачный. В Python вы для каждого типа определяете свою функцию проверки, а в Ruby обходитесь обобщённым методом. Никто не мешает в Питоне точно также определить одну единственную обобщённую функцию и просто вызывать её как `blank(obj)`, а не `obj.blank()`.
А пример неудачный. В Python вы для каждого типа определяете свою функцию проверки, а в Ruby обходитесь обобщённым методом. Никто не мешает в Питоне точно также определить одну единственную обобщённую функцию и просто вызывать её как `blank(obj)`, а не `obj.blank()`.
Вполне удачный, покажите мне реализацию этой функции.
Если дословно, то так:
В зависимости от нужного вам поведения проверять можно на конкретные типы, другие атрибуты или что угодно ещё. Возможно, в Ruby есть какие-то фишки, недоступные в Python, но написать внешнюю функцию, заменающую внутренний метод, можно всегда.
def blank(obj):
if hasattr(obj, '__iter__'): # или любая аналогичная проверка для нужных типов
return len(obj)
else:
return not bool(obj)
В зависимости от нужного вам поведения проверять можно на конкретные типы, другие атрибуты или что угодно ещё. Возможно, в Ruby есть какие-то фишки, недоступные в Python, но написать внешнюю функцию, заменающую внутренний метод, можно всегда.
По поводу порядка сборки среди исполнения, а в ruby она именно что собирается из всего дерева исходников, это в принципе меня никогда не подлавливало в реальных проектах. Есть правила как именно надо раскладывать свой код, и чего делать не стоит. Может вам просто попалась плохая библиотека.
Механизм-то сам по себе замечательный, но приводит к тотальному манкипатчингу при полном непонимании как и когда его правильно использовать… Впрочем такая проблема есть и с паттернами из Банды Четырех.
Да ни к чему он не приводит, я не понимаю о чем вы таком говорите — в моих проектах и в библиотеках которые я использую, такого нет. А хреновый код пишется хреновыми программистами, вне связи с языками.
Я именно про это и написал :\
Впрочем такая проблема есть и с
Вы пишете про некую проблему, которой нет ;) это мне напоминает войны java vs python на предмет private и protected.
Впрочем, как уже отметили выше, в Питоне совсем наговнокодить не выйдет, ибо
TypeError: can't set attributes of built-in/extension type INSERT_TYPE_NAME
, а в Ruby (насколько я знаю, поправьте если я неправ) переопределение аттрибутов/методов встроенных типов/классов возможно… И вот здесь и начинается АДЪ.В ruby все возможно. Только ада нет.
Возможность переопределения аттрибутов/методов у стандартных типов/классов — потенциальная дыра в безопасности приложения.
Не используйте интерпретируемые языки — в них часто можно переопределить множество вещей. Не используйте интернет — там можно ходить на другой компьютер. Не используйте компьютер — там можно писать в память.
Чем возможность дописывать в стандартные классы так опасна в сравнении с возможностью писать не в стандартные? Откуда вообще опасность? Покажете мне пример эксплуатации? ;) В rails находили много дырявостей, но открытые классы еще ни в одном случае не были причиной ужасной опасности.
Чем возможность дописывать в стандартные классы так опасна в сравнении с возможностью писать не в стандартные? Откуда вообще опасность? Покажете мне пример эксплуатации? ;) В rails находили много дырявостей, но открытые классы еще ни в одном случае не были причиной ужасной опасности.
1) Дописывание — хорошо, переписывание — зло;
2) Опасность в переопределение методов стандартных классов заключается в возможном исполнении этих методов (привет blackhat-сообщество);
3) Не покажу, абсолютно не знаю Руби. По маштабам — представьте переопределение escape-методов для любой ORM;
Призываю chikey в тред ;)
2) Опасность в переопределение методов стандартных классов заключается в возможном исполнении этих методов (привет blackhat-сообщество);
3) Не покажу, абсолютно не знаю Руби. По маштабам — представьте переопределение escape-методов для любой ORM;
Призываю chikey в тред ;)
Ну какие еще хакеры? Зачем вы даете им писать в свой проект? Ну если NSA приглашали, то им же удобнее, правда?
И потому, ну что вы в самом деле, escape никогда не определялся на встроенных типах.
И потому, ну что вы в самом деле, escape никогда не определялся на встроенных типах.
Объясните пожалуйста, я правильно понял (не знаю ruby), что вы взяли и какому-то стандартному классу поменяли поведение? Я б за такое по рукам бил. Берешь стандартный класс, используешь его, а у него другое поведение…
Как же, всё-таки, прекрасно, что в питоне так не делают!
Это абсолютно логично, что в питоне так не делают, потому что в нем делают по другому, что никоим образом не делает способ, которым это делают в ruby хоть сколько-нибудь неверным.
В питоне вообще ни коим образом не меняют поведение базовых объектов, а monkey patching стандартных и не очень библиотек считается не просто дурным тоном, а чем-то, за что полагается смерть через колесование. Исключения есть, но они настолько явные, что никаких вопросов не остаётся.
Я про то, что ни одному зрелому питонщику не придёт в голову писать статью про то, как круто править чужие объекты. Потому что это не круто.
Я про то, что ни одному зрелому питонщику не придёт в голову писать статью про то, как круто править чужие объекты. Потому что это не круто.
Открытые классы в Руби — это один из инструментов для реализации DSL.
Это очень удобно, например, когда это какой нибудь файл конфигурации, который не зависит от сторонних библиотек и файлов.
В проектах, расширение
Пример:
Включение такого файла приведет к поломке кодовой базы содержащей подобный код:
Это очень удобно, например, когда это какой нибудь файл конфигурации, который не зависит от сторонних библиотек и файлов.
В проектах, расширение
Object
'а может привести к проблемам.Пример:
class Object
def name
end
end
Включение такого файла приведет к поломке кодовой базы содержащей подобный код:
if my_obj.respond_to?(:name)
puts 'my_obj has name'
end
Sign up to leave a comment.
Открытые классы в ruby, заметки для питонистов