Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement an abstract class in ruby?

People also ask

How do you implement abstraction in Ruby?

In Ruby, we can use access specifiers like private, public and protected to achieve data abstraction. When we declare a member as public in a class, then that member can be accessed from anywhere in the program. If we declare a member as private, then that member can only be accessed from within the class.

How do you define an abstract class in Ruby?

Data Abstraction in Classes: we can use classes to perform data abstraction in ruby. The class allows us to group information and methods using access specifiers (private, protected, public). The Class will determine which information should be visible and which is not.

How do you implement an abstract class?

To implement features of an abstract class, we inherit subclasses from it and create objects of the subclass. A subclass must override all abstract methods of an abstract class. However, if the subclass is declared abstract, it's not mandatory to override abstract methods.

What is abstract class and how it is implemented?

Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.


Just to chime in late here, I think that there's no reason to stop somebody from instantiating the abstract class, especially because they can add methods to it on the fly.

Duck-typing languages, like Ruby, use the presence/absence or behavior of methods at runtime to determine whether they should be called or not. Therefore your question, as it applies to an abstract method, makes sense

def get_db_name
   raise 'this method should be overriden and return the db name'
end

and that should be about the end of the story. The only reason to use abstract classes in Java is to insist that certain methods get "filled-in" while others have their behavior in the abstract class. In a duck-typing language, the focus is on methods, not on classes/types, so you should move your worries to that level.

In your question, you're basically trying to recreate the abstract keyword from Java, which is a code-smell for doing Java in Ruby.


I don't like using abstract classes in Ruby (there's almost always a better way). If you really think it's the best technique for the situation though, you can use the following snippet to be more declarative about which methods are abstract:

module Abstract
  def abstract_methods(*args)
    args.each do |name|
      class_eval(<<-END, __FILE__, __LINE__)
        def #{name}(*args)
          raise NotImplementedError.new("You must implement #{name}.")
        end
      END
      # important that this END is capitalized, since it marks the end of <<-END
    end
  end
end

require 'rubygems'
require 'rspec'

describe "abstract methods" do
  before(:each) do
    @klass = Class.new do
      extend Abstract

      abstract_methods :foo, :bar
    end
  end

  it "raises NoMethodError" do
    proc {
      @klass.new.foo
    }.should raise_error(NoMethodError)
  end

  it "can be overridden" do
    subclass = Class.new(@klass) do
      def foo
        :overridden
      end
    end

    subclass.new.foo.should == :overridden
  end
end

Basically, you just call abstract_methods with the list of methods that are abstract, and when they get called by an instance of the abstract class, a NotImplementedError exception will be raised.


Try this:

class A
  def initialize
    raise 'Doh! You are trying to instantiate an abstract class!'
  end
end

class B < A
  def initialize
  end
end

for anyone in the rails world, implementing an ActiveRecord model as an abstract class is done with this declaration in the model file:

self.abstract_class = true

class A
  private_class_method :new
end

class B < A
  public_class_method :new
end

In the last 6 1/2 years of programming Ruby, I haven't needed an abstract class once.

If you're thinking you need an abstract class, you're thinking too much in a language that provides/requires them, not in Ruby as such.

As others have suggested, a mixin is more appropriate for things that are supposed to be interfaces (as Java defines them), and rethinking your design is more appropriate for things that "need" abstract classes from other languages like C++.

Update 2019: I haven’t needed abstract classes in Ruby in 16½ years of use. Everything that all of the folks commenting on my response are saying is addressed by actually learning Ruby and using the appropriate tools, like modules (which even give you common implementations). There are people on teams I have managed who have created classes that have base implementation that fail (like an abstract class), but these are mostly a waste of coding because NoMethodError would produce the exact same result as an AbstractClassError in production.