"Interfaces & Abstract Classes Unnecessary in Ruby" -> Can Someone Explain

Interfaces & Abstract Classes unnecessary in Ruby -- Can someone explain?

I am also Ruby starter. From my understanding, there is a closer rival for abstract classes in ruby. that is module. you can't create any instances of module but you can include with another class. So a target class will get the whole functionality of parent

  module Log
def write
//blah
end
end

class EventLog
include Log

def Prepare
end
end

In statically typed languages like java/C# , Interfaces enforce the classes to have all the methods at compile time. Since Ruby is dynamic, there is no meaning in it.

For more clarity, check these posts why dynamic languages don't require interfaces..

  1. why-dont-we-require-interfaces-in-dynamic-languages
  2. why-do-dynamic-languages-like-ruby-and-python-not-have-the-concept-of-interfaces

Cheers

Why Ruby doesn't support abstract classes?

If you are considering abstract classes or interfaces, you are most likely thinking of creating some kind of contract to your code.

However, Ruby is designed to be a weakly-typed is not designed to be a statically typed language and does rely heavily on duck typing. Obviously, it might be really useful in some cases to perform an interface check (to ensure the passed object would support all needed methods, for instance), but it is still will be done at run time, rendering the feature practically useless.

As far as I remember, there was an intention to create a typed version or Ruby and Dave Thomas even mentioned a person who tried this and told that it is not working out well :)

Why do dynamic languages like Ruby and Python not have the concept of interfaces like in Java or C#?

Thanks to late binding, they do not need it. In Java/C#, interfaces are used to declare that some class has certain methods and it is checked during compile time; in Python, whether a method exists is checked during runtime.

Method overloading in Python does work:

>>> class A:
... def foo(self):
... return "A"
...
>>> class B(A):
... def foo(self):
... return "B"
...
>>> B().foo()
'B'

Are they object-oriented? I'd say yes. It's more of an approach thing rather than if any concrete language has feature X or feature Y.

Can someone help explain abstract classes and interfaces to me (novice)?

Well, all that interfaces do are state required implementation. A contract, if you will, that the inheriting class will implement their own versions of those methods with the same parameters and return values.

Abstract classes are similar, except they can implement generic implementation without requiring the inheriting classes to implement it.

Another difference is, that one class can implement multiple interfaces but only inherit from one possibly abstract class.

That's my understanding of it anyways. Hope I helped!

How to implement an abstract class 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.

What is java interface equivalent in Ruby?

Ruby has Interfaces just like any other language.

Note that you have to be careful not to conflate the concept of the Interface, which is an abstract specification of the responsibilities, guarantees and protocols of a unit with the concept of the interface which is a keyword in the Java, C# and VB.NET programming languages. In Ruby, we use the former all the time, but the latter simply doesn't exist.

It is very important to distinguish the two. What's important is the Interface, not the interface. The interface tells you pretty much nothing useful. Nothing demonstrates this better than the marker interfaces in Java, which are interfaces that have no members at all: just take a look at java.io.Serializable and java.lang.Cloneable; those two interfaces mean very different things, yet they have the exact same signature.

So, if two interfaces that mean different things, have the same signature, what exactly is the interface even guaranteeing you?

Another good example:

package java.util;

interface List<E> implements Collection<E>, Iterable<E> {
void add(int index, E element)
throws UnsupportedOperationException, ClassCastException,
NullPointerException, IllegalArgumentException,
IndexOutOfBoundsException;
}

What is the Interface of java.util.List<E>.add?

  • that the length of the collection does not decrease
  • that all the items that were in the collection before are still there
  • that element is in the collection

And which of those actually shows up in the interface? None! There is nothing in the interface that says that the Add method must even add at all, it might just as well remove an element from the collection.

This is a perfectly valid implementation of that interface:

class MyCollection<E> implements java.util.List<E> {
void add(int index, E element)
throws UnsupportedOperationException, ClassCastException,
NullPointerException, IllegalArgumentException,
IndexOutOfBoundsException {
remove(element);
}
}

Another example: where in java.util.Set<E> does it actually say that it is, you know, a set? Nowhere! Or more precisely, in the documentation. In English.

In pretty much all cases of interfaces, both from Java and .NET, all the relevant information is actually in the docs, not in the types. So, if the types don't tell you anything interesting anyway, why keep them at all? Why not stick just to documentation? And that's exactly what Ruby does.

Note that there are other languages in which the Interface can actually be described in a meaningful way. However, those languages typically don't call the construct which describes the Interface "interface", they call it type. In a dependently-typed programming language, you can, for example, express the properties that a sort function returns a collection of the same length as the original, that every element which is in the original is also in the sorted collection and that no bigger element appears before a smaller element.

So, in short: Ruby does not have an equivalent to a Java interface. It does, however, have an equivalent to a Java Interface, and it's exactly the same as in Java: documentation.

Also, just like in Java, Acceptance Tests can be used to specify Interfaces as well.

In particular, in Ruby, the Interface of an object is determined by what it can do, not what class it is, or what module it mixes in. Any object that has a << method can be appended to. This is very useful in unit tests, where you can simply pass in an Array or a String instead of a more complicated Logger, even though Array and Logger do not share an explicit interface apart from the fact that they both have a method called <<.

Another example is StringIO, which implements the same Interface as IO and thus a large portion of the Interface of File, but without sharing any common ancestor besides Object.

Interface vs Base class


Let's take your example of a Dog and a Cat class, and let's illustrate using C#:

Both a dog and a cat are animals, specifically, quadruped mammals (animals are waaay too general). Let us assume that you have an abstract class Mammal, for both of them:

public abstract class Mammal

This base class will probably have default methods such as:

  • Feed
  • Mate

All of which are behavior that have more or less the same implementation between either species. To define this you will have:

public class Dog : Mammal
public class Cat : Mammal

Now let's suppose there are other mammals, which we will usually see in a zoo:

public class Giraffe : Mammal
public class Rhinoceros : Mammal
public class Hippopotamus : Mammal

This will still be valid because at the core of the functionality Feed() and Mate() will still be the same.

However, giraffes, rhinoceros, and hippos are not exactly animals that you can make pets out of. That's where an interface will be useful:

public interface IPettable
{
IList<Trick> Tricks{get; set;}
void Bathe();
void Train(Trick t);
}

The implementation for the above contract will not be the same between a cat and dog; putting their implementations in an abstract class to inherit will be a bad idea.

Your Dog and Cat definitions should now look like:

public class Dog : Mammal, IPettable
public class Cat : Mammal, IPettable

Theoretically you can override them from a higher base class, but essentially an interface allows you to add on only the things you need into a class without the need for inheritance.

Consequently, because you can usually only inherit from one abstract class (in most statically typed OO languages that is... exceptions include C++) but be able to implement multiple interfaces, it allows you to construct objects in a strictly as required basis.

In Ruby, what is the equivalent to an interface in C#?

There are no interfaces in ruby since ruby is a dynamically typed language. Interfaces are basically used to make different classes interchangeable without breaking type safety. Your code can work with every Console as long it behaves like a console which in C# means implements IConsole. "duck typing" is a keyword you can use to catch up with the dynamic languages way of dealing with this kind of problem.

Further you can and should write unit tests to verify the behavior of your code. Every object has a respond_to? method you can use in your assert.

Why do most system architects insist on first programming to an interface?

Programming to an interface means respecting the "contract" created by using that interface. And so if your IPoweredByMotor interface has a start() method, future classes that implement the interface, be they MotorizedWheelChair, Automobile, or SmoothieMaker, in implementing the methods of that interface, add flexibility to your system, because one piece of code can start the motor of many different types of things, because all that one piece of code needs to know is that they respond to start(). It doesn't matter how they start, just that they must start.



Related Topics



Leave a reply



Submit