Хотя я согласен с тем, что расширение нативных типов и объектов - плохая практика, наследование от них не должно быть.
В предположительно поддерживающем геме (который я не смог найти) способ, которым нативные типы былибудет использоваться следующим образом:
require 'cool-unkown-light-gem'
class MyTypedArray < CoolArray # would love to directly < Array
def initialize(*args)
super(*args)
# some inits for DataArray
@caches_init = false
end
def name?(name)
init_caches unless !@caches_init
!!@cache_by_name[name]
end
def element(name)
init_caches unless !@caches_init
@cache_by_name[name]
end
private
# overrides the CoolArray method:
# CoolArray methods that modify self will call this method
def on_change
@caches_init = false
super
end
def init_caches
return @cache_by_name if @caches_init
@caches_init = true
@cache_by_name = self.map do |elem|
[elem.unique_name, elem]
end.to_h
end
end
Любой метод родительского класса, не переопределенный дочерним классом, который изменяет self, вызовет, скажем (в данном случае), функцию on_change
.Что позволило бы не переопределять каждый из этих методов, чтобы избежать потери отслеживания изменений.
Скажем, MyTypedArray
будет массив Foo
объектов:
class Foo
attr_reader :unique_name
def initialize(name)
@unique_name = name
end
end
краткий пример ожидаемого поведения его использования:
my_array = MyTypedArray.new
my_array.push( Foo.new("bar") ).push( Foo.new("baz") )
my_array.element("bar").unique_name
# => "bar"
my_array.shift # a method that removes the first element from self
my_array.element("bar").unique_name
# => undefined method `unique_name' for nil:NilClass (NoMethodError)
my_array.name?("bar")
# => false
Я понимаю, что мы должны искать неизменяемые классы, но эти нативные типы поддерживают изменения в одном и том же объекте, и мы хотим сделать правильный способнаследство, которое является максимально коротким и простым.
Любые мысли, подходы или рекомендации, конечно, приветствуются.Я не думаю, что я единственный, кто задумался над этим.
Причина, по которой я ищу поддерживаемый гем, заключается в том, что разные версии ruby могут предлагать разные поддерживаемые методы или опции для собственных типов / классов.
[Редактировать]
Цель вышеизложенного состоит в том, чтобы выяснить, какая модель работает.Я мог бы просто следовать правилам и предложениям других постов, но при этом не мог бы заставить вещи работать так, как я намеревался, и когда я это вижу правильно (язык кодирования создан людьми и для людей, а не люди созданы для языков кодирования).Я знаю, что каждый гордится своими достижениями в обучении, разработке и создании вещей в форме, хорошо известной в сообществе.
Цель вышесказанного состоит в том, что все methods
из Array
более чем приветствуются.Мне все равно, если в версии 20 Ruby они уберут некоторые методы Array.К тому времени мое приложение устареет, или кто-то достигнет того же результата с гораздо меньшим количеством кода.
Почему Array
?
Поскольку порядок имеет значение.
Почему внутренний Hash
?
Поскольку для использования, которое я хочу использовать, в целом, стоимость создания хеша компенсирует предлагаемую оптимизацию.
Почему бы просто не include Enumerable
?
Поскольку мы просто сокращаем количество методов, которые изменяют объект, но у нас фактически нет шаблона, который позволяет изменять @caches_init
до false
, поэтому Hash
перестраивается при следующем использовании (такая же проблема, как и с Array
)
Почему бы просто не включить белый список и включить целевые Array
методы ?
Потому что это не дает мне того, кем я хочу быть.Что если я хочу, чтобы кто-нибудь все еще использовал pop
или shift
, но я не хочу переопределять их, или даже беспокоиться о том, чтобы управлять моими миксинами и постоянно использовать responds_to?
?(возможно, это упражнение полезно для улучшения ваших навыков кодирования и чтения кода от других людей, но это не то, чем оно должно быть)
Где я хочу быть ?
Я хочу быть в том положении, чтобы я мог повторно использовать / наследовать любой, повторяю, любой класс (независимо от того, является ли он нативным или нет).Это является основным для языка ООП.И если мы не говорим о языке ООП (а просто о некотором сахаре наверху, чтобы он выглядел как ООП), то давайте оставим себя открытыми для анализа шаблонов, которые должны хорошо работать (независимо от того, являются ли они странными - для меняболее странно, что промежуточных уровней нет, что является признаком многих традиционных моделей, что, в свою очередь, является признаком плохой поддержки определенных функций, которые требуются более широко, чем то, что принято).
Почемудолжен ли драгоценный камень предлагать выше ?
Хорошо, давай смиримся.Выше приведен очень простой случай (и даже не охваченный).В какой-то момент вы можете добиться большей гибкости, используя то, что некоторые люди хотят назвать Ruby way .Но по цене, когда вы переходите на более крупные архитектуры.Что если я хочу создать промежуточные классы для наследования?Обогащенные нативные классы, которые улучшают простой код, сохраняя его в соответствии с языком.Проще сказать , что это не Ruby , чем пытаться приблизить язык к чему-то, что хорошо растет снизу.
Я не удивлен, что Rails и Ruby почти "невнятно "используется многими.Потому что в какой-то момент, без какой-либо поддержки Rails, то, что у вас есть с Ruby, - большая проблема.Следовательно, я не удивлен, что Rails так поддерживается.
Зачем мне переопределять методы pop
, last
или first
?Для чего?Они уже реализованы.Почему я должен занести в белый список методы и создавать миксины?это объектно-ориентированное программирование?
Во всяком случае ... Я не ожидаю, что кто-то поделится своим мнением по этому поводу.Я вижу другие паттерны и буду позволять своему уму их находить.Если кто-то достаточно открыт, пожалуйста, не стесняйтесь поделиться.Кто-то может критиковать этот подход и быть правым, но если он у вас есть, значит, он сработал.