Reputation: 1332
module A
module B
class Foo
def initialize(args)
@args = args
end
def call
puts 'Inside Foo'
end
end
end
end
module C
class Boo
def initialize(args)
@args = args
end
def call
puts 'Inside Boo'
A::B::Foo.new(@args).call
end
end
end
boo = C::Boo.new(nil).call
# Inside Boo
# Inside Foo
A::B::Foo.new(nil).call
# Inside Foo
How can I avoid A::B::Foo.new(nil).call
?
It should be accessible only from Boo
class.
If anybody wants to access Foo
class they will be able to access it from Boo
.
How can I achieve this ?
Searched Internet but could not find what should be call this concept ?
Upvotes: 1
Views: 59
Reputation: 28285
This is ruby - so there's no such thing as an iron-clad way of making an object "private". (For example, you can access private methods via .send
!) But you can at least define a private interface.
However, your interface doesn't actually make much sense from an OOP perspective. Why is A::B::Foo
accessible only within C::Boo
? If A::B::Foo
is private, then it should only be accessible within A::B
, and nowhere else.
The key method you're looking for is: private_constant
And you can circumvent a private constant lookup exception by using const_get
.
Therefore we can "hack" your current implementation to work as follows:
module A
module B
class Foo
def initialize(args)
@args = args
end
def call
puts 'Inside Foo'
end
end
private_constant :Foo
end
end
module C
class Boo
def initialize(args)
@args = args
end
def call
puts 'Inside Boo'
A::B.const_get(:Foo).new(@args).call
end
end
end
# This works:
C::Boo.new(nil).call
# This errors:
A::B::Foo.new(nil).call
Upvotes: 3