So I came across an issue when I was working on some api code and realized I could call a protected method outside of a module even though the docs doesn't specify this is possible.
Example:
module Root
class Test1
protected def hello
puts "world"
end
end
end
include Root
test = Test1.new
test.hello
Outputs "world" live example here
Expected behavior: When I call a protected method outside of a module it should spit out "protected method called" error. The default functionality based on the docs should still allow access to protected methods when called inside a module's scope.
Actual behavior: No error is called when I call a protected method outside of a module scope. It seems as if when I include the Root module above it puts the whole file inside that scope? I could be wrong, but that's just a guestimate.
Other: Someone ran a similar test in ruby and it has the desired effect
â—‹ ruby test.rb test.rb:12:in `<main>': protected method `hello' called for #<Root::Test1:0x007fd8700457e0> (NoMethodError)`
According to the docs:
A protected method can only be invoked on:
- instances of the same type as the current type
- instances in the same namespace (class, struct, module, etc.) as the current type
When you include it in the top-level, it is now in the same namespace as it.
This is different than Ruby, but then again Crystal is not Ruby :-)
So it does make the whole file the top level once included, that seems kind of odd though.
I guess my question now is why use protected methods at all if they are that easy to get access to? In a top level file.
Just don't include types in the top-level. Antyhing that's global is a bad smell.
Still doesn't answer my question, what's the point of protected methods in crystal in comparison to other languages.
Most helpful comment
So it does make the whole file the top level once included, that seems kind of odd though.
I guess my question now is why use protected methods at all if they are that easy to get access to? In a top level file.