Reputation: 944
I read that it is not possible to have several constructors for a class. So the following code won't work:
class C
def initialize x
initialize x,0
end
# Some methods using the private constructor…
def foo
# …
bar = C.new 3,4
# …
end
private
def initialize x,y
@x = x
@y = y
end
end
I have thought about replacing the public constructor by a static method, but that would prevent other classes to extend C
. I also have thought about making a private post-initializing method:
class C
def initialize x
post_init x,0
end
# Some methods using the private constructor…
def foo
# …
bar = C.new baz
bar.post_init 3,4
# …
end
private
def post_init x,y
@x = x
@y = y
end
end
But here, the post_init is called twice, which is not a good thing.
Is there a way to give a public constructor, while having in private a more complete way to make a new instance? If not, what is the best way to do something similar?
Upvotes: 0
Views: 106
Reputation: 1173
I guess this would do what you expect.
class C
def initialize(x, y = 0)
@x = x
@y = y
end
def self.with_position
new(3, 4)
end
end
c1 = C.new(5)
c2 = C.with_position
If you want to prohibit setting y
by anyone from outside the class, you can use some private method behind the scenes (as you suggested) and konstructor gem
class C
def initialize(x)
set_coords(x, 0)
end
konstructor
def with_position
set_coords(3, 4)
end
private
def set_coords(x, y)
@x = x
@y = y
end
end
c1 = C.new(5)
c2 = C.with_position
Upvotes: 1
Reputation: 26758
A simple way is to accept options for initialize, you can have an if
statement in there that covers the private or public cases.
Ruby doesn't really have this concept of 'private class' in a simple way such as saying 'private'.
You can see How to I make private class constants in Ruby for a way to make a private constant (since classes are constants). You'd make a class method that returns an anonymous class (Class.new do ... end
). Then mark that class method private with private_class_method
.
A better solution would be to make two classes with different initializes. Common functionality could be in a separate class or module. If it's a class, then the way to include them in the 'public/private' classes would be inheritance. If it's a module, then you'd include/extend
.
Upvotes: 1