我天真地尝试了以下方法:
class Policy class << self def lookup(object) #returns a subclass by analyzing the given object, following a naming convention end def inherited( sub ) sub.class_eval { remove_method :lookup } end end end
当然这不起作用,因为子类没有方法,它在超类上.之后我尝试了:
def inherited( sub ) class << Policy remove_method :lookup end end
这就像一个魅力,哈哈,除了它的工作的微小细节,通过在第一次加载子类时从超类中取出该方法.哎呀!
所以,由于Ruby查找方法的方式,我很确定这不起作用.
我感兴趣的原因是,在我正在处理的行为中,根据命名约定,您可以有许多不同的策略,并且我希望有一个很好的干净方法来获取对任何其他类的策略的引用对象.对我来说,在语法上,这样做似乎很好:
class RecordPolicy < Policy # sets policy concerning records, # inherits common policy behavior from Policy end class Record end $> record = Record.new => #<Record:0x0000> $> Policy.lookup(record) => RecordPolicy
但是,我认为能够调用RecordPolicy#lookup没有任何意义.你有这个政策,下面找不到任何东西.
所以,我的问题是两部分:
1)事实上,是否有某种方法可以有选择地定义哪些类方法可以在Ruby中继承?
在这一点上,我非常肯定答案是否定的,因此:
2)鉴于我想封装用于在任何地方推断任何给定对象的策略名称的逻辑,并且它看起来像我到目前为止所尝试的那样表明Policy类是错误的地方,你会把它放在哪里这种事情呢?
谢谢!
更新
感谢JimLim回答第1部分,感谢Linuxios回复第2部分.非常有用的见解.
FWIW,在反思了Linuxios所说的内容后,我决定这样做:
class << self def lookup( record ) if self.superclass == Policy raise "No default naming convention exists for subclasses of Policy. Override self.lookup if you want to use it in a subclass." else # naming convention lookup goes here end end end
我觉得这对于如何使用这段代码是最不令人惊讶的事情.如果某人有某种理由在子类上提供#lookup方法,他们可以设置一个,但如果他们调用继承的方法,他们会得到一个异常,告诉他们这样做是没有意义的.
至于如何决定谁得到“答案”,因为他们都回答了我的问题的一半,我个人习惯在“领带”的情况下接受当时声誉较低的人的答案.
谢谢你们的帮助!
undef_method
似乎工作.根据文件,
Prevents the current class from responding to calls to the named
method. Contrast this with remove_method, which deletes the method
from the particular class; Ruby will still search superclasses and
mixed-in modules for a possible receiver.
class Policy def self.lookup(object) end end class RecordPolicy < Policy class << self undef_method :lookup end end Policy.lookup nil # => nil RecordPolicy.lookup # => NoMethodError: undefined method `lookup' for RecordPolicy:Class
使用#inherited,我们可以做到
class Policy def self.lookup(object) end def self.inherited(sub) sub.class_eval do class << self undef_method :lookup end end end end class RecordPolicy < Policy end RecordPolicy.lookup # => NoMethodError: undefined method `lookup' for RecordPolicy:Class
使用sub.class_eval {undef_method:lookup}将不起作用,因为这将取消定义RecordPolicy的实例方法.它需要在RecordPolicy的本征类上调用.