2009-10-14 60 views
44
class A 
private 
    def initialize 
    puts "wtf?" 
    end 
end 

A.new #still works and calls initialize 

如何讓類構造函數在Ruby中是私有的?

class A 
private 
    def self.new 
    super.new 
    end 
end 

不起作用完全

那麼,什麼是正確的方法是什麼?我想讓new保密,並通過工廠方法進行調用。

+0

我不確定你想要什麼是可能的,但即使它在理論上是你的將無法從工廠方法調用它,因爲它是私有的。你想創建一個單身人士嗎?或者做一個反轉控制模式? – Matt 2009-10-14 16:27:55

回答

67

試試這個:

class A 
    private_class_method :new 
end 

More on APIDock

+6

如果你想要實現一個Singleton類(我可以想到想要一個私有構造函數的唯一原因),Ruby會爲你做。 http://apidock.com/ruby/Singleton – adurity 2009-10-14 16:37:19

+2

即使有人可以做A.send(:new)。 (順便說一下,不應該「類」是小寫?) – 2009-10-15 06:58:59

+0

是的,它應該。現在更正。 – adurity 2009-10-16 21:47:16

13

你嘗試過代碼的第二塊是差不多吧。問題是private正在實例方法而不是類方法的上下文中操作。

要獲得privateprivate :new工作,你只需要強制它是在類的方法是這樣的背景下:

class A 
    class << self 
    private :new 
    end 
end 

或者,如果你真的想重新定義new,並呼籲super

class A 
    class << self 
    private 
    def new(*args) 
     super(*args) 
     # additional code here 
    end 
    end 
end 

類級工廠方法可以訪問私有new就好了,而是試圖直接使用new會失敗,因爲new是私有的實例。

+0

Upvoted,因爲這是一個完全有效的方法,使類私人方法。六年前我不知道開班的課程。 :) – 2015-10-08 19:58:05

1

要闡明的使用一些光,這裏是工廠方法的一個常見的例子:

class A 
    def initialize(argument) 
    # some initialize logic 
    end 

    # mark A.new constructor as private 
    private_class_method :new 

    # add a class level method that can return another type 
    # (not exactly, but close to `static` keyword in other languages) 
    def self.create(my_argument) 
    # some logic 
    # e.g. return an error object for invalid arguments 
    return Result.error('bad argument') if(bad?(my_argument)) 

    # create new instance by calling private :new method 
    instance = new(my_argument) 
    Result.new(instance) 
    end 
end 

然後用它作爲

result = A.create('some argument')  

如所預期的,在的情況下發生的運行時錯誤直接new用法:

a = A.new('this leads to the error') 
相關問題