【问题标题】:Integer and other (?) abstract classes in RubyRuby 中的整数和其他(?)抽象类
【发布时间】:2015-06-24 13:08:13
【问题描述】:

我承认在鸭式语言中,抽象类并不经常使用,所以这个问题更多是出于好奇而不是实际需要:

在 Ruby(至少 2.0)中,FixnumBignum 有一个共同的超类,称为 Integer。在我看来,这是一个抽象类;至少,它不能被实例化,即当你在 irb 中这样做时:

irb(main):047:0> Integer.new(8)
NoMethodError: undefined method `new' for Integer:Class
    from (irb):47
    from /usr/bin/irb:12:in `<main>'

现在,如果我决定推出自己的类,其行为类似于 Integer,即“像 Integer 一样抽象”,我会怎么做?我认为 每个 类都包含一个(隐藏的)new 方法(如果存在,它将调用我的 initialize 方法)。

【问题讨论】:

  • 像这样严格执行的抽象基类确实违背了通常的 Ruby 风格。如果你真的,真的需要对人们实例化你的类感到讨厌:def initialize; raise "Nope"; end 然后让子类重新定义它。
  • 我认为这不能回答我的问题。或者,Ruby 的整数类是否有可能引发“NoMethodError:未定义的方法‘新’”?如果是这种情况,我认为堆栈跟踪将显示“初始化”作为异常的来源,不是吗?
  • @BinaryMee:这也不能解释我得到的例外的措辞。

标签: ruby


【解决方案1】:

您可以在您的类的singleton class 上取消定义调用undef_methodnew 类方法,例如:

class Foo
  class << self
    undef_method(:new)
  end
end

Foo.new
# NoMethodError: undefined method `new' for Foo:Class

或者:

class Foo; end
Foo.singleton_class.send(:undef_method, :new)

更新:为了完整起见,这里有一个快速(可能是肮脏)的解决方案,以解决 @tadman 在 cmets 中提到的问题。它使用inherited 方法为Foo 的子类定义一个new 单例方法,模仿Class#new 的实现:

class Foo
  class << self
    undef_method(:new)

    def inherited(subclass)
      subclass.define_singleton_method(:new) do |*args|
        obj = subclass.allocate
        obj.send(:initialize, *args)
        obj
      end
    end
  end

end

class Bar < Foo
  attr_reader :bar
  def initialize(bar)
    @bar = bar
  end
end

Bar.new('foobar').bar # => "foobar" 

【讨论】:

  • 还有undef关键字。
  • 不要忘记,这意味着您需要将其重新添加到可能会变得混乱的子类中。
  • @toro2k:我认为您的解决方案是正确的。它至少解释了我从实例化整数中看到的效果。我想知道为什么 Ruby 核心类被定义为抽象的。这是鸭式语言中很少使用的概念....
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 2013-12-25
  • 1970-01-01
相关资源
最近更新 更多