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

Leo*_*sov 52 ruby constructor access-specifier

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

A.new #still works and calls initialize
Run Code Online (Sandbox Code Playgroud)

class A
private
  def self.new
    super.new
  end
end
Run Code Online (Sandbox Code Playgroud)

不起作用

那么正确的方法是什么?我想new私有化并通过工厂方法调用它.

adu*_*ity 77

试试这个:

class A
  private_class_method :new
end
Run Code Online (Sandbox Code Playgroud)

更多关于APIDock

  • @adurity,您可能还想拥有专门的工厂方法. (16认同)
  • 如果你想要实现一个Singleton类(我想到想要私有构造函数的唯一原因),Ruby会为你做.http://apidock.com/ruby/Singleton (7认同)
  • 您可能希望私有构造函数允许类以您不信任外部调用者的方式创建自身实例 - 例如直接分配给其他初始化程序不可变或隐藏的受保护变量 (6认同)
  • @adurity:也许你想要实现一种严格的方法来创建对象.例如:Quote.for_truck(卡车)和Quote.for_car(汽车),但您不希望允许人们从头开始构建报价. (4认同)
  • 即便如此,有人也可以做A.send(:new).(顺便说一下,不应该"小组"是小写?) (2认同)

Nat*_*han 13

您尝试的第二块代码几乎是正确的.问题是private在实例方法而不是类方法的上下文中操作.

要获得privateprivate :new工作,您只需要强制它在类方法的上下文中,如下所示:

class A
  class << self
    private :new
  end
end
Run Code Online (Sandbox Code Playgroud)

或者,如果你真的想重新定义new并打电话super

class A
  class << self
    private
    def new(*args)
      super(*args)
      # additional code here
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

类级工厂方法可以正常访问私有new,但尝试直接使用实例化new将失败,因为它new是私有的.


Art*_*tru 5

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

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
Run Code Online (Sandbox Code Playgroud)

然后将其用作

result = A.create('some argument')    
Run Code Online (Sandbox Code Playgroud)

如预期的那样,在直接new使用的情况下会发生运行时错误:

a = A.new('this leads to the error')
Run Code Online (Sandbox Code Playgroud)