Классы в Ruby-интерфейс?
У меня есть следующие классы:
CachedObject
CachedObjectSource
CachedObjectDbSource < CachedObjectSource
CachedObjectDalliSource < CachedObjectSource
CachedObject-это объект без базы данных, который извлекается из стороннего API и хранится локально. CachedObject будет храниться как в базе данных, так и в Dalli (memcache), код реального времени будет пинговать источник Dalli для копии объекта, а источник Dalli будет искать источник базы данных и обновлять его кэш, если объект не существует. Таким образом, это вложенный вызов, требующий каждого дочернего класса CachedObjectSource реализовать тот же набор методов. Т. е. интерфейс.
есть ли способ написать класс CachedObjectSource, чтобы его дочерние классы должны реализовать интерфейс? Я делаю что-то не так?
3 ответов
Ruby не знает интерфейсов, подобных, например, Java. Вместо этого программы Ruby обычно используют подход, называемый Утиной Типизацией что в основном означает, что вы можете отправить любое сообщение любому объекту, который затем может решить, будет ли он отвечать на это, т. е. каждый объект сам решает, какие методы у него есть.
самое близкое, что вы можете получить к "интерфейсу", - это класс (или модуль), который реализует метод, но только поднимает NotImplementedError
аналогично это:
class CachedObjectSource
def my_method
raise NotImplementedError, "Implement this method in a child class"
end
end
таким образом, метод будет присутствовать и вернуть здравое ошибка при вызове без перезаписи в дочернем классе. Затем вы должны написать некоторую документацию, разъясняющую, какие дочерние классы должны реализовывать, чтобы быть совместимыми.
вы можете использовать камень интерфейс.
Этот камень имитирует интерфейсы похожи на интерфейсы 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
этот драгоценный камень, который полезен вместе с аннотация камень.
Абстрактный камень предоставляет абстрактные методы.
вы также можете использовать Ринт
gem 'rint'
это поставляется с CLI:
$ rint c CachedObjectSourceInterface my_method
создаст определение интерфейса, но вы также можете добавить его вручную в любой класс. Затем вы можете сделать что-то вроде:
class Instrument
implements CachedObjectSourceInterface
end
и это вызовет значимое исключение, если метод my_method
не выполнены.