Prefer to inherit from abstract classes that have pure virtual functions 
with no implementation and no state.

Use the Dependency Inversion Principle: High Level modules should not 
depend upon low level modules, both should depend on abstractions. 
Abstractions should not depend on details, rather details should depend on 
abstractions.

Rubyizing that....

Ruby does not have a notion of "pure virtual" function like C++. Or the 
notion of an "interface" like Java.

Partly it doesn't matter since Ruby duck-types. You don't need to inherit 
from a common abstract class. But still I like to collect the signature of 
the "duck" somewhere so sometimes I use this idiom...

class AbstractFoo
   # Description...
   def signature_1( a, b, c)
     raise "Pure virtual"
   end

   # Description...
   def signature_2( d, e)
     raise "Pure virtual"
   end
end

class ConcreteA < AbstractFoo
   def signature_1( a, b, c)
   end

   def signature_2( d, e)
   end
end


I also have my nifty "quacks_like" assertion..


class BigHairyThing
   def does_lots( thing)
     thing.quacks_like( :duck) # Assert


     thing.duck
   end
end

====================================================

# Abstract base class for all the type check exceptions
class TypeCheckException  < Exception
end

# This exception is thrown in event of a method being invoked with an
# object of the wrong duck type.
class DuckTypingException < TypeCheckException
end

# This exception is thrown in event of a method being invoked with a
# parameter of of the wrong static type.
class StaticTypeException < TypeCheckException
end

# This exception is thrown in event of a method being invoked with a
# parameter of of the wrong polymorphic type.
class PolymorphicTypeException < TypeCheckException
end


class Object

   # Raise a DuckTypingException unless the object responds to all symbol.
   def quacks_like( *symbols)
     symbols.each do |symbol|
       raise DuckTypingException, "Duck typing error, expected this object 
to respond to :#{symbol}, but found class #{self.class}" unless
         respond_to? symbol
     end
   end

   def static_type_check( klass)
     raise StaticTypeException, "Static type check error, expected object 
to be exactly class '#{klass}', found '#{self.class}'" unless
       self.class == klass
   end

   def polymorphic_type_check( klass)
     raise PolymorphicTypeException, "Polymorphic type check error, 
expected object to be a kind of '#{klass}', found '#{self.class}'" unless
       self.kind_of? klass
   end


end


if $0 == __FILE__ then
   require 'test/unit'

   class TC_Utilities < Test::Unit::TestCase

     def test_utilities
       assert_raise( DuckTypingException) { nil.quacks_like( :call)}
       assert_raise( DuckTypingException) { 1.quacks_like( :+, :call)}
       1.quacks_like( :+, :-, :*)

       assert_raise( StaticTypeException) { nil.static_type_check( String)}

       assert_raise( PolymorphicTypeException) 
{"foo".polymorphic_type_check( Array)}

       begin
         2.static_type_check( String)
       rescue TypeCheckException => details
         puts details
       end
       begin
         2.polymorphic_type_check( String)
       rescue TypeCheckException => details
         puts details
       end
     end
   end

end


John Carter                             Phone : (64)(3) 358 6639
Tait Electronics                        Fax   : (64)(3) 359 4632
PO Box 1645 Christchurch                Email : john.carter / tait.co.nz
New Zealand

Carter's Clarification of Murphy's Law.

"Things only ever go right so that they may go more spectacularly wrong later."

From this principle, all of life and physics may be deduced.