Ruby interface classes?

13,605

Solution 1

Ruby doesn't know interfaces similar to e.g. Java. Instead, Ruby programs typically use an approach called Duck Typing which basically means that you can send any message to any object which then can decide if it will respond to that, i.e. each object decides on its own which methods it has.

The closest thing you can get to an "interface" is a class (or module) that implements a method but only raises a NotImplementedError similar to this:

class CachedObjectSource
  def my_method
    raise NotImplementedError, "Implement this method in a child class"
  end
end

That way, the method will be present and return a sensible error when called without being overwritten in a child class. Then, you should write some documentation making it clear what child classes have to implement to be compliant.

Solution 2

You can use the gem interface.
This gem emulates interfaces similar to Java interfaces.
For example:

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

This gem which is useful together with abstract gem.
Abstract gem provides abstract methods.

Solution 3

You could also use rint

gem 'rint'

that comes with a CLI:

$ rint c CachedObjectSourceInterface my_method

will create an interface definition, but you can also add it manually to any class. Then you can do something like:

class Instrument 
  implements CachedObjectSourceInterface
end

and it will throw a meaningful Exception if the method my_method is not implemented.

Share:
13,605
kid_drew
Author by

kid_drew

Updated on July 05, 2022

Comments

  • kid_drew
    kid_drew almost 2 years

    I have the following classes:

    CachedObject
    CachedObjectSource
    CachedObjectDbSource < CachedObjectSource
    CachedObjectDalliSource < CachedObjectSource
    

    CachedObject is a non-database object that is getting pulled from a third-party API and stored locally. CachedObject will be stored in both the database and Dalli (memcache), the real-time code will ping the Dalli source for a copy of the object, and the Dalli source will search the database source and update its cache if the object does not exist. So it's a nested call that requires each child class of CachedObjectSource to implement the same set of methods. IE, an interface.

    Is there a way to write the CachedObjectSource class so that its child classes must implement the interface? Am I going about this the wrong way?