【问题标题】:Default behavior for unimplemented methods?未实现方法的默认行为?
【发布时间】:2015-12-22 04:00:40
【问题描述】:

我有一个子类,我想为一组方法实现一些默认行为,例如,如果我知道我需要重写该方法,但如果该方法尚不支持,现在只想打印一个警告在这个特定的子类上。

我可以像这样覆盖子类中的每个方法,但我想知道是否有更简单的方法,可能使用委托或 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

【问题讨论】:

  • 为什么不在Foo类中将这些方法定义为not_yet_supported
  • alias可以帮到你吗?
  • @sawa 我或多或少地将其用于类似复合的模式。 Foo 的大多数方法都可以在 Bar 实例上调用,但有些方法在 Bar 实例上调用没有意义,所以对于那组方法,我想打印一个警告(或者可能引发异常)。所以我真的只是在寻找一种 DRYer 方法(并不是说用一个衬里实现每种方法都那么糟糕)。
  • “调用 Bar 实例的某些方法没有意义” - 如果这是真的,继承在这里可能不是一个好的选择。子类应该是其超类的特化。如果它们只有一些重叠的行为,那么通过模块进行组合可能会更好。
  • @Kristján 我不同意您的评论,但在复合材料中,叶子和复合材料的界面应该相同,但行为可能会有所不同,这基本上就是我在这里所做的。某些方法在复合与叶子上调用时不会做任何事情,我只是在寻找一种方法将所有这些方法名称分组到一个列表中,然后调用一些常见的功能(如警告)。

标签: ruby oop


【解决方案1】:

按照 cmets 的建议使用 alias or alias_method 是一条简单的路线,看起来像

alias         method_b   not_yet_supported
alias_method :method_c, :not_yet_supported

注意语法差异,因为alias 是关键字,alias_method 是方法。

如果你想声明一个完整的不受支持的方法列表,一点元编程就可以了:

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

【讨论】:

  • 我忘记了define_method
【解决方案2】:

更简洁的方法是使用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

method_missing的更友好的解释也可以找到here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2015-07-31
    • 2023-04-04
    • 2017-10-21
    • 2014-12-06
    • 2022-10-13
    • 1970-01-01
    相关资源
    最近更新 更多