I was just wondering: does access control not apply to class methods? When I use the public, private and protected keywords on my instance methods everything works fine, but when I try to do the same on class methods they all end up being public anyway.
A small example:
--- Snip ---
#!/usr/bin/ruby
class Foo
public
def Foo._public (x)
puts "Hello in a public way #{x}"
end
protected
def Foo._protected (x)
puts "Hello in a protected way #{x}"
end
private
def Foo._private (x)
puts "Hello in a private way #{x}"
end
end
Running this small program will call all three methods successfully meaning that the private and protected class methods are called from a place where _only_ public methods should be available.
So, are there no access control mechanisms for class methods? Or am i missing domething here?
Best regards,
Mads D. Kristensen
BTW: Thanks to the creators of Ruby for a great little language. Good work you guys!
class Bar
class<<self
public
def _public (x)
puts "Hello in a public way #{x}"
end
protected
def _protected (x)
puts "Hello in a protected way #{x}"
end
private
def _private (x)
puts "Hello in a private way #{x}"
end
end
end
Bar::_public(1)
Bar::_protected(2)
Bar::_private(3)
__END__
Hello in a public way 1
C:/rubylib/experiments/ruby-talk/access-control-on-class-methods.rb:40:
protected method `_protected' called for Bar:Class (NoMethodError)
Regards
Sean
···
On 11/6/05, Mads Kristensen <madsk@foo.bar> wrote:
I was just wondering: does access control not apply to class methods?
It just doesn't work when done in this way becuase public, private and
protected are only effecting the incance level, so you need to get to
the class's "instance level", i.e. the class level.
class Foo
class << self
public
def _public (x)
puts "Hello in a public way #{x}"
end
protected
def _protected (x)
puts "Hello in a protected way #{x}"
end
private
def _private (x)
puts "Hello in a private way #{x}"
end
end
end
It just doesn't work when done in this way becuase public, private and
protected are only effecting the incance level, so you need to get to
the class's "instance level", i.e. the class level.
OK. Thanks a lot for the swift reply.
But... it seems a bit messy though doesn't it? I mean, if defining a class method should be done with the "inner class" syntax you have just described to make the access control work, why is it at all possible to define a class method using the "ClassName.methodName" syntax?
Ambiguities like that are no good in programming languages
And BTW: what does class<<self actually mean? One < would be inheritance but what does it mean when there are two?
One of the early hurdles I had with Ruby was trying to map
the "class <<object" syntax into a useful mental model. I'm
not sure why "<<" was selected. The semantics and syntax
don't seem to be related to those of the "<<" operator and
so you really need to form two separate mental models and just
know which one applies.
Why not something like:
class obj.eclass
···
On Nov 6, 2005, at 9:47 AM, Mads Kristensen wrote:
And BTW: what does class<<self actually mean? One < would be inheritance but what does it mean when there are two?
#
end
Where Object#eclass is defined to return the eigenclass of
the receiver? Even a different keyword would be clearer:
And BTW: what does class<<self actually mean? One < would be inheritance but what does it mean when there are two?
One of the early hurdles I had with Ruby was trying to map
the "class <<object" syntax into a useful mental model. I'm
not sure why "<<" was selected. The semantics and syntax
don't seem to be related to those of the "<<" operator and
so you really need to form two separate mental models and just
know which one applies.
Well, it does bear some relation to inheritance which is why,
I would assume, the syntax was chosen. This...
class << foobar
# ...
end
...to me reads something like 'create an unnamed class which
inherits from foobar' and while not entirely accurate, illustrates
the basic idea of creating a special class/object based on some
existing object (foobar above) and defining behaviours on it.
In actuality, of course, the relationship is inverted as we are
not inheriting foobar but indeed making foobar inherit from a
new class but the end result behaves more or less the same.
Why not something like:
class obj.eclass
#
end
Where Object#eclass is defined to return the eigenclass of
the receiver? Even a different keyword would be clearer:
eclass obj
#
end
There was some debate about what the class should be called
(I still think #pouch). Also, the irreplaceable _why took it
upon himself to write a good description of Ruby's metaclasses.
There is also a small set of methods towards the bottom to help
dealing with metaclasses. Wrap it up in a file, put a notice
thanking _why for his contribution and use it with your code.
It isn't a big deal but it does confuse newbies.
Gary Wright
E
···
On Nov 6, 2005, at 9:47 AM, Mads Kristensen wrote:
And BTW: what does class<<self actually mean? One < would be inheritance but what does it mean when there are two?
One of the early hurdles I had with Ruby was trying to map
the "class <<object" syntax into a useful mental model. I'm
not sure why "<<" was selected. The semantics and syntax
don't seem to be related to those of the "<<" operator and
so you really need to form two separate mental models and just
know which one applies.
Why not something like:
class obj.eclass
#
end
Once you know what << does, there is no confusion. I suspect the same would be with your proposed code above. By looking at it, I am confused, but once I know what it means, there is no more confusion.
Zach
···
On Nov 6, 2005, at 9:47 AM, Mads Kristensen wrote:
This is all part of the confusion. An object is not a subclass
of its eigenclass so there is no class/subclass relationship
being asserted by the 'class <<object' syntax. The fact that
the symbol '<' is *also* used to assert a subclass relationship
in a similar notation (class A < B) hints at some sort of
subclassing assertion related to the object that doesn't exist.
The notation is a semantic head-fake.
Gary Wright
···
On Nov 6, 2005, at 9:45 PM, Eero Saynatkari wrote:
class << foobar
# ...
end
[..]
In actuality, of course, the relationship is inverted as we are
not inheriting foobar but indeed making foobar inherit from a
new class but the end result behaves more or less the same.
Once you know what << does, there is no confusion.
Isn't that a truism?
As I said in my first post, I found the notation a
stumbling block for understanding the concept. Based
on the number of questions about the syntax that show
up on ruby-talk, I don't think my experience was particularly
unique.
I suspect the same would be with your proposed code above. By looking at it, I am confused, but once I know what it means, there is no more confusion.
There is a difference between a notation that is not suggestive
of anything in particular (an "empty vessel") and a notation that
is suggestive of something that is unrelated.
In any case, I was just throwing out some ideas for thought.
Here is another one:
Ruby currently allows for:
module M; end
class Y; end
class X < Y; end
class <<x; end
How about just using
object x; end
to open up the singleton class? This sort of goes with my previous thought
that we can think of an object and its eigenclass as simply two views of
the same object.
>
> Once you know what << does, there is no confusion.
Isn't that a truism?
As I said in my first post, I found the notation a
stumbling block for understanding the concept. Based
on the number of questions about the syntax that show
up on ruby-talk, I don't think my experience was particularly
unique.
Personally, I found the "class << object" *extremely* good at describing the
concept it referred to. As soon as I understood the *concept*, I found it made
sense, and helped me not to forget what the concept meant.
There is a difference between a notation that is not suggestive
of anything in particular (an "empty vessel") and a notation that
is suggestive of something that is unrelated.
I disagree that the notation is suggestive of something unrelated. YMMV.
In any case, I was just throwing out some ideas for thought.
Here is another one:
Ruby currently allows for:
module M; end
class Y; end
class X < Y; end
class <<x; end
How about just using
object x; end
to open up the singleton class? This sort of goes with my previous
thought
that we can think of an object and its eigenclass as simply two views of
the same object.
Using "object" to open up a *class* is about the most unintuitive thing I've
ever read. Using a new keyword like "eclass" unjustifiably favours one
denomination for those classes ("eigenclass") above others, while there is
still *no* agreement on how to call them (AFAIK, matz himself still prefers to
call them singleton classes).
I still don't understand why the "class << object" notation is considered
unintuitive. I myself read it as "enter the singleton class of the particular
object". "<<" fits the "enter/come in" meaning quite well, and taken that way
it is pointing in the right direction: you're entering a class.
And can understand this mental model of the syntax. It is what I've come to
understand also. My point was that it is a *different* mental model than
what I use for:
class A < B; end.
The A and B here have different relationship than the object/singleton
class relationship.
Gary Wright
···
On Nov 7, 2005, at 3:36 AM, Christophe Grandsire wrote:
I still don't understand why the "class << object" notation is considered
unintuitive. I myself read it as "enter the singleton class of the particular
object". "<<" fits the "enter/come in" meaning quite well, and taken that way
it is pointing in the right direction: you're entering a class.
And can understand this mental model of the syntax. It is what I've
come to
understand also. My point was that it is a *different* mental model
than
what I use for:
class A < B; end.
The A and B here have different relationship than the object/singleton
class relationship.
True. That's why you don't use "<" but "<<". Different relationship, different
syntax. And I don't think the similarity of the two symbols is so close that
it's problematic. I mean, one can write:
"string" < "other string" and
"string" << "other string"
and so far I've never seen someone complain that those two symbols are too
similar for the completely different meanings they have. If one can accept that
with strings '<' means comparison while '<<' means concatenation, why cannot
they accept that after the keyword 'class' '<' means subclassing while '<<'
means getting the singleton class?
I can accept it. Semantic overloading happens all the time in
programming languages and natural languages. It also can be
confusing during the learning process or if the overloaded definitions
are only vaguely related. Of course once the overloaded meanings
have been internalized, it all seems much clearer than it did before.
Another Ruby example that bit me because of my C and C++ background: Kernel#include.
It took me a long time to get my head around the fact that #include is not some
sort of directive to read and interpret a file. Its behavior isn't at all related
to the #include functionality of C and C++.
I was poking around to see if there was any historical debate on
overloading the left shift operator ('<<') for use with IO and then
by extension with other sorts of concatenation behavior. I found this
interesting example:
// Demonstrate shift operators #include <iostream>
using namespace std;
int main() {
cout << "5 times 2 is " << (5 << 1) << endl
<< "20 divided by 4 is " << (20 >> 2) << endl;
}
The prose around this example neglected to explain that '<<' is used
in two vastly different ways. This would be pretty difficult
to digest if you didn't already understand how the semantics of '<<' had
been overloaded.
Gary Wright
···
On Nov 7, 2005, at 10:06 AM, Christophe Grandsire wrote:
If one can accept that with strings '<' means comparison while '<<'
means concatenation, why cannot
they accept that after the keyword 'class' '<' means subclassing while '<<'
means getting the singleton class?