How to make the class constructor private in Ruby?
class A
private
def initialize
puts "wtf?"
end
end
A.new #still works and calls initialize
and
class A
private
def self.new
super.new
end
end
doesn't work altogether
So what's the correct way? I want to make new
private and call it via a factory method.
Solution 1:
Try this:
class A
private_class_method :new
end
More on APIDock
Solution 2:
The second chunk of code you tried is almost right. The problem is private
is operating in the context of instance methods instead of class methods.
To get private
or private :new
to work, you just need to force it to be in the context of class methods like this:
class A
class << self
private :new
end
end
Or, if you truly want to redefine new
and call super
class A
class << self
private
def new(*args)
super(*args)
# additional code here
end
end
end
Class-level factory methods can access the private new
just fine, but trying to instantiate directly using new
will fail because new
is private.
Solution 3:
To shed some light on the usage, here is a common example of the factory method:
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
Then use it as
result = A.create('some argument')
As expected, the runtime error occurs in the case of direct new
usage:
a = A.new('this leads to the error')