Классы в 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 не выполнены.