2017-09-06 85 views
1

爲什麼我們不能在Ruby中初始化TrueClass?我得到這個:爲什麼我們不能在Ruby中初始化TrueClass

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

但,TrueClasssuperclassObject

同樣,我們無法初始化NilClassFalseClass

我只是想知道這樣是可能的,即使是子類的Object。如果我們想寫一個類似這樣的課程,我們如何實現它?

+0

你想要達到什麼目的? –

+0

只是我很想知道它是如何禁止創建新的對象? – Sanjith

+0

您是否閱讀過文檔? https://ruby-doc.org/core-2.2.0/TrueClass.html –

回答

7

我只是想知道這樣是可能的,即使是在對象的子類。如果我們想寫一個類似這樣的課程,我們如何實現它?

您可以使用關鍵字undef取消定義繼承的方法。由於new是一種類方法,因此您必須在類的單例類中使用undef。這看起來像這樣:

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

我只是想知道即使這是Object的子類也是如此。

它通過undefining allocatenew工作。這裏的corresponding C code

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 

不幸的是,rb_undef_alloc_func在Ruby中不可用。我們可以通過重寫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> 

爲了考慮所有這些特殊情況,紅寶石」 STDLIB提供Singleton模塊:

require 'singleton' 

class Foo 
    include Singleton 
end 

它通過使allocatenew私有方法:(間​​)

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

,並將其添加instance返回一個實例:(或情況下,只有一個)

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

謝謝@stefan。我明白一點。所以,我的第二個問題出現了:我們可以寫一個類似於這樣的類嗎? – Sanjith

相關問題