如何在Ruby中使类构造函数成为私有的?

时间:2009-10-14 16:18:54

标签: ruby constructor access-specifier

class A
private
  def initialize
    puts "wtf?"
  end
end

A.new #still works and calls initialize

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

完全不起作用

那么正确的方法是什么?我想将new设为私有,并通过工厂方法调用它。

3 个答案:

答案 0 :(得分:75)

试试这个:

class A
  private_class_method :new
end

More on APIDock

答案 1 :(得分: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是私有的。

答案 2 :(得分:3)

为了阐明用法,以下是工厂方法的常见示例:

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')