По своему опыту знаю, что открытые классы в ruby раздражают и вызывают непонимание в среде питонистов. Ну в самом деле, что за странность открыть класс String и переопределить там size?
А можно рассмотреть вопрос в другой стороны, попробуем разобрать небольшой пример. Все знают как в python разные типы проверяются на истинность — всё что пусто, то ложь. В ruby это не так, здесь ложь это nil и false. Иногда было бы удобнее как в python.
Как это можно решить например в rust, включая поддержку для встроенных типов:
trait Existable {
fn exist(&self) -> bool;
}
impl Existable for int {
fn exist(&self) -> bool { if *self == 0 { false } else { true } }
}
fn main () {
assert!(5.exist() == true)
assert!(0.exist() == false)
}
Представим что в python схема не такая, и мы хотим ее реализовать. В python нельзя определить новые методы для сторонних классов, поэтому можно сделать что-то вроде:
class Trait(object):
def __init__(self):
self.registry = {}
def impl(self, typ):
def reg(func):
self.registry[typ] = func
return func
return reg
def __call__(self, arg):
return self.registry[arg.__class__](arg)
Existable = Trait()
@Existable.impl(int)
def int_exists(i):
return False if i == 0 else True
if __name__ == '__main__':
assert Existable(0) == False
assert Existable(5) == True
Ну или использовать какую-нибудь библиотеку, которая толковее минутного наброска.
Как в ruby реализовали подобную штуку?
class Object
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 13
def blank?
respond_to?(:empty?) ? empty? : !self
end
end
Метод `empty?` определен на классах `Array` и `Hash` (как минимум). Определите на своем классе и метод `blank?` будет корректно работать. То есть здесь мы имеем trait в ruby — объекты отвечающие на `empty?` реализуют trait проверки на пустоту, тот самый `Existable`.
Это простейший корректный пример использования открытых классов в ruby, а есть и много других замечательных штук из ActiveSupport, одной из частей Ruby on Rails.
Надеюсь благодаря такому простому примеру, вы теперь понимаете, что открытые классы в ruby вовсе не зло, а полезный инструмент, который в прямых руках позволяет реализовывать расширения среды изящно.
Если было не совсем понятно, что я имею в виду — открытые классы в ruby позволяют доопределять поведение любых, встроенных в том числе, классов, также как и traits в rust и других языках.
PS Я не утверждаю что в python нельзя реализовать подобный механизм — я простенький пример даже привел в самой статье. Еще раз — речь о правильном использовании открытых классов в ruby, а не о преимуществах какого-либо языка перед другим.
Автор: Deepwalker