Abstract methods in ruby?


#1

Hi everybody !

How do you implement something like the “abstract” keyword in Java ?
Or: Is there a technique to force a subclass to implement a special
method ?

Kind regards

Dominik


#2

On Jul 11, 2007, at 5:40 PM, removed_email_address@domain.invalid wrote:

How do you implement something like the “abstract” keyword in Java ?
Or: Is there a technique to force a subclass to implement a special
method ?

One way is:

class Parent
def abstract_method
raise NotImplementedError
end
end

You may just want to skip this step altogether though, since an
exception toss is the default behavior.

Welcome to the word of dynamic typing. :wink:

James Edward G. II


#3

Thanks a lot for the warm welcome, James :slight_smile:

2007/7/12, James Edward G. II removed_email_address@domain.invalid:


#4

On 7/12/07, James Edward G. II removed_email_address@domain.invalid wrote:

 raise NotImplementedError

end
end

You may just want to skip this step altogether though, since an
exception toss is the default behavior.

Hmm, I would say no, you will be caught by #method_missing one day.
It would be interesting why you want to do this?

For documentation purpose? ( Dumbs up !!)

Because you want the feature? (Dumbs down :wink:
I have not really yet seen a need for an abstract method in Ruby.
If you are looking for warnings or errors for subclasses not
implementing the abstract method you will be disappointed at Compile
Time [which arguabley does not even exist in 1.8]

If you are happy with the runtime exception (because you do nice code
covering tests :wink: James’ solution is ideal, anyway you cannot do
better ( or worse for must of us;) in Ruby.

Welcome to the word of dynamic typing. :wink:

Yes indeed, welcome :slight_smile:

James Edward G. II

Robert


#5

On Jul 11, 5:44 pm, James Edward G. II removed_email_address@domain.invalid
wrote:

 raise NotImplementedError

end
end

You may just want to skip this step altogether though, since an
exception toss is the default behavior.

Welcome to the word of dynamic typing. :wink:

James Edward G. II

It’s true that an exception toss is the default behavior, but it’s a
NoMethodError instead of a NotImplementedError and that could be an
important distinction, depending. And I agree with Robert D. that
it could get you caught by method_missing one day.

What gets me about NoMethodError is you get that whether there’s no
method at all (which follows from the name) or as a result of going
against access control (calling a private or protected method).


#6

Hi,

Not sure if this has been mentioned already, but you might also be
interested in checking out http://rubyforge.org/projects/abstract/

George


#7

On Jul 12, 2007, at 7:05 AM, Robert D. wrote:

class Parent
def abstract_method
raise NotImplementedError
end
end

You may just want to skip this step altogether though, since an
exception toss is the default behavior.

Hmm, I would say no, you will be caught by #method_missing one day.
It would be interesting why you want to do this?

If someone adds a method_missing() implementation to a child class
that accepts messages it shouldn’t, there is a bug in that
implementation and it needs to be fixed. Your tests are going to
catch that for you.

For documentation purpose?

That is about the best reason to add the stub, I think.

If you are looking for warnings or errors for subclasses not
implementing the abstract method you will be disappointed at Compile
Time [which arguabley does not even exist in 1.8]

class AbtractClass
REQUIRED_METHODS = %w[one two three]

def self.inherited(subclass)
REQUIRED_METHODS.each do |m|
raise “An implementation of #{m} is required by #{self.class}”
unless subclass.instance_methods.include? m
end
end
end

class Broken < AbtractClass
def one; end
def two; end
end

~> -:7:in `inherited’: An implementation of one is required by

Class (RuntimeError)

~> from -:5:in `each’

~> from -:5:in `inherited’

~> from -:12

But don’t do that. :wink:

James Edward G. II


#8

On 7/12/07, James Edward G. II removed_email_address@domain.invalid wrote:

     unless subclass.instance_methods.include? m

~> from -:5:in `each’

~> from -:5:in `inherited’

~> from -:12

But don’t do that. :wink:
That does not work as you have intended, it is complaining about #one
missing as a matter of fact:

531/31 > cat subclass.rb && ruby subclass.rb

vim: sw=2 ts=2 ft=ruby

class P
def self.inherited(subclass)
puts “P --> #{subclass}”
end
end

class C < P
puts “in C”
end
P --> C
in C

Robert


#9

removed_email_address@domain.invalid wrote/schrieb
removed_email_address@domain.invalid:

Or: Is there a technique to force a subclass to implement a special method ?

Alternatively try something similiar to the the NVI idiom in C++:

interface

module MyInterface
def foo(*args, &block)
do_foo(args, block)
end
end

special implementation of interface

class MyClass
include MyInterface

private
def do_foo(args, block)
  # TODO complete implementation
end

end

Regards
Thomas


#10

On Jul 12, 2007, at 9:17 AM, Robert D. wrote:

def self.inherited(subclass)
def two; end
end

~> -:7:in `inherited’: An implementation of one is required by

Class (RuntimeError)

~> from -:5:in `each’

~> from -:5:in `inherited’

~> from -:12

But don’t do that. :wink:
That does not work as you have intended, it is complaining about #one
missing as a matter of fact:

You are right. My mistake.

James Edward G. II