Интерфейсы интерфейса Ruby?
У меня есть следующие классы:
CachedObject
CachedObjectSource
CachedObjectDbSource < CachedObjectSource
CachedObjectDalliSource < CachedObjectSource
CachedObject - это объект без базы данных, который извлекается из стороннего API и хранится локально. CachedObject будет храниться как в базе данных, так и в Dalli (memcache), код реального времени будет пинговать источник Dalli для копии объекта, а источник Dalli будет искать источник базы данных и обновлять его кеш, если объект не существует, Таким образом, это вложенный вызов, который требует, чтобы каждый дочерний класс CachedObjectSource реализовал один и тот же набор методов. IE, интерфейс.
Есть ли способ написать класс CachedObjectSource, чтобы его дочерние классы реализовали интерфейс? Я иду об этом неправильно?
Ответы
Ответ 1
Ruby не знает интерфейсы, подобные, например, Ява. Вместо этого в Ruby-программах обычно используется подход Duck Typing, который в основном означает, что вы можете отправлять любое сообщение любому объекту, который затем может решить, будет ли он отвечать к этому, т.е. каждый объект сам решает, какие методы он имеет.
Ближайшая вещь, которую вы можете получить в "интерфейсе", - это класс (или модуль), который реализует метод, но вызывает только NotImplementedError
:
class CachedObjectSource
def my_method
raise NotImplementedError, "Implement this method in a child class"
end
end
Таким образом, метод будет присутствовать и возвращать разумную ошибку при вызове без перезаписи в дочернем классе. Затем вы должны написать некоторую документацию, в которой ясно, какие дочерние классы должны внедряться для соответствия требованиям.
Ответ 2
Вы можете использовать gem interface.
Этот жемчуг эмулирует интерфейсы, аналогичные интерфейсам Java.
Например:
require 'interface'
MyInterface = interface{
required_methods :foo, :bar, :baz
}
# Raises an error until 'baz' is defined
class MyClass
def foo
puts "foo"
end
def bar
puts "bar"
end
implements MyInterface
end
Этот драгоценный камень, который полезен вместе с abstract gem.
Абстрактный камень содержит абстрактные методы.
Ответ 3
Вы также можете использовать rint
gem 'rint'
который поставляется с CLI:
$ rint c CachedObjectSourceInterface my_method
создаст определение интерфейса, но вы также можете добавить его вручную в любой класс. Затем вы можете сделать что-то вроде:
class Instrument
implements CachedObjectSourceInterface
end
и он выдает осмысленное исключение, если метод my_method
не реализован.