![](/img/trans.png)
[英]Why the `singleton` methods can't be defined on `Fixnum`,`Bignum`,`Float`,`Symbol` class objects, but ` FalseClass` and `TrueClass` can have?
[英]Why can't we initialize TrueClass in Ruby
為什么我們TrueClass
在Ruby中初始化TrueClass
? 我得到這個:
TrueClass.new # => NoMethodError: undefined method `new' for TrueClass:Class
但是, TrueClass
superclass
是Object
。
同樣,我們無法初始化NilClass
和FalseClass
我只是想知道即使這是Object
的子類,這也是可行的。 如果我們想編寫一個與此類似的類,我們如何實現呢?
我只是想知道即使這是Object的子類,這也是可行的。 如果我們想編寫一個與此類似的類,我們如何實現呢?
您可以使用undef
關鍵字undef
定義繼承的方法。 由於new
是一個類方法,因此您必須在該類的singleton類內使用undef
。 看起來像這樣:
class <<MyClass
undef new
end
MyClass.new # NoMethodError: undefined method `new' for MyClass:Class
我只是想知道即使這是Object的子類,這也是可行的。
它通過取消定義allocate
和new
。 這是相應的C代碼 :
rb_undef_alloc_func(rb_cTrueClass);
rb_undef_method(CLASS_OF(rb_cTrueClass), "new");
您可以通過undef_method
在Ruby中獲得類似的結果:
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>
“相似”,因為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的stdlib提供了Singleton
模塊:
require 'singleton'
class Foo
include Singleton
end
它通過allocate
和new
私有方法來工作:(除其他更改外 )
Foo.new #=> NoMethodError: private method `new' called for Foo:Class
Foo.allocate #=> NoMethodError: private method `new' called for
並且它添加了一個instance
,該實例返回一個實例:(或該實例,只有一個)
Foo.instance #=> #<Foo:0x007fdca11117e8>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.