当前位置 : 主页 > 编程语言 > ruby >

Ruby:选择性类继承?

来源:互联网 收集:自由互联 发布时间:2021-06-23
所以,我一直在玩一些模型,我遇到了一种情况,我真的想通过子类来限制类方法的继承.麻烦的是,我的实验到目前为止证实了我的理解,这是不可能做到的. 我天真地尝试了以下方法: cla
所以,我一直在玩一些模型,我遇到了一种情况,我真的想通过子类来限制类方法的继承.麻烦的是,我的实验到目前为止证实了我的理解,这是不可能做到的.

我天真地尝试了以下方法:

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的本征类上调用.

网友评论