为什么我们不能在Ruby中初始化TrueClass

时间:2017-09-06 08:57:08

标签: ruby

为什么我们不能在Ruby中初始化TrueClass?我明白了:

TrueClass.new # => NoMethodError: undefined method `new' for TrueClass:Class

superclass的{​​{1}}为TrueClass

同样,我们无法初始化ObjectNilClass

我只是想知道即使那是FalseClass的子类也是如此。如果我们想写一个类似于此的类,我们怎样才能实现呢?

2 个答案:

答案 0 :(得分:7)

  

我只是想知道即使那是Object的子类也是如此。如果我们想写一个类似于此的类,我们怎样才能实现呢?

您可以使用undef关键字取消定义继承的方法。由于new是一种类方法,因此您必须在类的单例类中使用undef。这看起来像这样:

class <<MyClass
  undef new
end
MyClass.new # NoMethodError: undefined method `new' for MyClass:Class

答案 1 :(得分:5)

  

我只是想知道即使那是Object的子类也是如此。

通过取消定义allocatenew来工作。这是corresponding C code

rb_undef_alloc_func(rb_cTrueClass);
rb_undef_method(CLASS_OF(rb_cTrueClass), "new");

您可以通过undef_method

中获得类似的结果
class FooClass
  ::FOO = new    # <- this will be the only Foo instance
  class << self
    undef_method :allocate
    undef_method :new
  end
end

FooClass.new      #=> NoMethodError: undefined method `new' for FooClass:Class
FooClass.allocate #=> NoMethodError: undefined method `allocate' for FooClass:Class

FOO #=> #<FooClass:0x007fddc284c478>

&#34;类似&#34;,因为TrueClass.allocate实际上并未提出NoMethodError,而是TypeError

TrueClass.allocate #=> TypeError: allocator undefined for TrueClass

不幸的是,Ruby中没有rb_undef_alloc_func。我们可以通过覆盖allocate

来模仿行为
class FooClass
  class << self
    def allocate
      raise TypeError, "allocator undefined for #{self}"
    end
    undef_method :new
  end
end

FooClass.allocate  #=> TypeError: allocator undefined for FooClass

不确定,哪种方法更清洁。

以上更改阻止您通过new创建实例,但还有其他方法:

FOO       #=> #<FooClass:0x007fddc284c478>

FOO.dup   #=> #<FooClass:0x007fad721122c8>
FOO.clone #=> #<FooClass:0x007f83bc157ba0>

Marshal.load(Marshal.dump(FOO)) #=> #<FooClass:0x007f83bc13e330>

为了解释所有这些特殊情况,Ruby&#39; stdlib提供Singleton模块:

require 'singleton'

class Foo
  include Singleton
end

通过制作allocatenew私有方法:( other changes之内)

Foo.new      #=> NoMethodError: private method `new' called for Foo:Class
Foo.allocate #=> NoMethodError: private method `new' called for

它添加了instance,它返回一个实例:(或 实例,只有一个实例)

Foo.instance #=> #<Foo:0x007fdca11117e8>