0

I have a subclass that I would like to implement some default behavior for a set of methods, for example if I know I need to override the method, but just want to print a warning for now if the method is not yet supported on this particular subclass.

I can override each method in the subclass, like so, but I was wondering if there was a easier way, maybe using delegate or method_missing?

class Foo

  def method_a
    # do foo stuff
  end

  def method_b
    # do foo stuff
  end

  def method_c
    # do foo stuff
  end

end


class Bar < Foo

  def not_yet_supported
    puts "warnnig not yet supported"
  end

  def method_b
    not_yet_supported
  end

end
kingsfoil
  • 3,795
  • 7
  • 32
  • 56
nPn
  • 16,254
  • 9
  • 35
  • 58
  • 2
    Why not define those methods as `not_yet_supported` in class `Foo`? – sawa Sep 24 '15 at 13:57
  • Can `alias` help you? – Nickolay Kondratenko Sep 24 '15 at 14:12
  • @sawa I using this as more or less in a composite like pattern. Most of the methods of Foo can be called on Bar instances, but some of the methods will not make sense to call on Bar instances, so for that set of methods, I would like to print a warning (or maybe raise an exception). So I was really just looking for a DRYer way (not that implementing each method with a one liner is that bad). – nPn Sep 24 '15 at 15:37
  • "some of the methods will not make sense to call on Bar instances" - If that's true, inheritance might not be a good choice here. A subclass should be a specialization of its superclass. If they only have some overlapping behavior, composition through modules might be better. – Kristján Sep 24 '15 at 15:39
  • @Kristján I don't disagree with your comment, but in a composite the interface should be the same for leafs and composites, but the behavior could be different, which is basically what I am doing here. Certain methods will not do anything when called on the composite vs the leaf, and I was just looking for a way to group all those method names into a list and then call some common functionality (like a warning). – nPn Sep 24 '15 at 16:05

2 Answers2

1

Using alias or alias_method as suggested in the comments is an easy route, and would look like

alias         method_b   not_yet_supported
alias_method :method_c, :not_yet_supported

Note the syntactic differences, since alias is a keyword and alias_method is a method.

If you want to declare a whole list of unsupported methods, a little metaprogramming gets you there:

class Foo
  def self.not_yet_supported(*method_names)
    method_names.each do |method_name|
      define_method method_name do
        puts "#{method_name} is not yet supported on #{self.class.name}"
      end
    end
  end

  not_yet_supported :bar, :baz
end
Community
  • 1
  • 1
Kristján
  • 18,165
  • 5
  • 50
  • 62
1

A cleaner approach would be to use method_missing:

class Foo    
    
  UNIMPLEMENTED_METHODS = [:method_a, :method_b, :method_etc]

  def method_missing(method_id)
    UNIMPLEMENTED_METHODS.include?(method_id) ? warn("#{method_id} has not been implemented") : raise(NoMethodError)
  end

end

A friendlier explanation of method_missing can also be found here

kingsfoil
  • 3,795
  • 7
  • 32
  • 56