为什么我们不能在Ruby中初始化TrueClass
?我明白了:
TrueClass.new # => NoMethodError: undefined method `new' for TrueClass:Class
但superclass
的{{1}}为TrueClass
。
同样,我们无法初始化Object
和NilClass
我只是想知道即使那是FalseClass
的子类也是如此。如果我们想写一个类似于此的类,我们怎样才能实现呢?
答案 0 :(得分:7)
我只是想知道即使那是Object的子类也是如此。如果我们想写一个类似于此的类,我们怎样才能实现呢?
您可以使用undef
关键字取消定义继承的方法。由于new
是一种类方法,因此您必须在类的单例类中使用undef
。这看起来像这样:
class <<MyClass
undef new
end
MyClass.new # NoMethodError: undefined method `new' for MyClass:Class
答案 1 :(得分:5)
我只是想知道即使那是Object的子类也是如此。
通过取消定义allocate
和new
来工作。这是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
通过制作allocate
和new
私有方法:( 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>