# Instance methods can't call protected class methods?

**URL:** <https://www.ruby-forum.com/t/instance-methods-cant-call-protected-class-methods/62632>\
**Category:** Ruby\
**Created:** [June 6, 2006, 8:31pm UTC](https://www.ruby-forum.com/t/instance-methods-cant-call-protected-class-methods/62632 "2006-06-06T20:31:43Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![seanhussey](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@seanhussey](https://www.ruby-forum.com/u/seanhussey)\
**Post date:** [June 6, 2006, 8:31pm UTC](https://www.ruby-forum.com/t/instance-methods-cant-call-protected-class-methods/62632/1 "2006-06-06T20:31:43Z")

</div>

I am trying to understand this behavior.

From page 356 of the Pickaxe (2nd ed):

Protected. Can be invoked only by objects of the defining class and its  
subclasses.

If I have

class Foo  
…  
end

f = Foo.new

Is f not an “object of the defining class”? If so, why should an  
instance method of Foo not be able to call a protected class method?

I’m not looking for an answer of the form “because in class scope,  
self.class.type.object.class # =\> Object, however in _instance_ scope”  
etc. Logically, why should it be this way?

In C++ it makes sense that a static class method cannot call an  
non-static method, since static methods exist even when there are no  
objects of the class in existence. However, they do not limit you on the  
reverse and prevent a non-static method from calling a static method.

---

<div class="post-metadata">

**Author:** ![seanhussey](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@seanhussey](https://www.ruby-forum.com/u/seanhussey)\
**Post date:** [June 6, 2006, 9:51pm UTC](https://www.ruby-forum.com/t/instance-methods-cant-call-protected-class-methods/62632/2 "2006-06-06T21:51:36Z")

</div>

where’s the problem?

class Test

protected  
def self.call\_me  
puts “static and protected”  
end

public  
def invoke\_me  
puts “try to call”  
Test.call\_me  
# this will _not_ work: self.call\_me  
puts “done”  
end

end

t = Test.new  
t.invoke\_me

> try to call  
> static and protected  
> done

Sean Hermany schrieb:

---

<div class="post-metadata">

**Author:** ![seanhussey](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@seanhussey](https://www.ruby-forum.com/u/seanhussey)\
**Post date:** [June 6, 2006, 10:06pm UTC](https://www.ruby-forum.com/t/instance-methods-cant-call-protected-class-methods/62632/3 "2006-06-06T22:06:42Z")

</div>

The problem is that self.call\_me is not protected.

class Test

protected  
def self.call\_me  
puts “static and protected”  
end

public  
def invoke\_me  
puts “try to call”  
Test.call\_me  
# this will _not_ work: self.call\_me  
puts “done”  
end

end

t = Test.new

print “Output of p Test.protected\_methods.sort:\n\n”

p Test.protected\_methods.sort

print “\nOutput of p Test.public\_methods.sort:\n\n”

p Test.public\_methods.sort

print “\n”

t.invoke\_me

## OUTPUT:

sean@jefferson:~$ ruby protected\_test.rb  
Output of p Test.protected\_methods.sort:

[]

Output of p Test.public\_methods.sort:

["\<", “\<=”, “\<=\>”, “==”, “===”, “=~”, “\>”, “\>=”, “ **id** ”, “ **send** ”,  
“allocate”, “ancestors”, “autoload”, “autoload?”, “call\_me”, “class”,  
“class\_eval”, “class\_variables”, “clone”, “const\_defined?”, “const\_get”,  
“const\_missing”, “const\_set”, “constants”, “display”, “dup”, “eql?”,  
“equal?”, “extend”, “freeze”, “frozen?”, “hash”, “id”, “include?”,  
“included\_modules”, “inspect”, “instance\_eval”, “instance\_method”,  
“instance\_methods”, “instance\_of?”, “instance\_variable\_get”,  
“instance\_variable\_set”, “instance\_variables”, “is\_a?”, “kind\_of?”,  
“method”, “method\_defined?”, “methods”, “module\_eval”, “name”, “new”,  
“nil?”, “object\_id”, “private\_class\_method”, “private\_instance\_methods”,  
“private\_method\_defined?”, “private\_methods”,  
“protected\_instance\_methods”, “protected\_method\_defined?”,  
“protected\_methods”, “public\_class\_method”, “public\_instance\_methods”,  
“public\_method\_defined?”, “public\_methods”, “respond\_to?”, “send”,  
“singleton\_methods”, “superclass”, “taint”, “tainted?”, “to\_a”, “to\_s”,  
“type”, “untaint”]

try to call  
static and protected  
done

- Sean

Pete wrote:

> where’s the problem?
> 
> class Test
> 
> protected  
> def self.call\_me  
> puts “static and protected”  
> end
> 
> public  
> def invoke\_me  
> puts “try to call”  
> Test.call\_me  
> # this will _not_ work: self.call\_me  
> puts “done”  
> end
> 
> end
> 
> t = Test.new  
> t.invoke\_me
> 
> > try to call  
> > static and protected  
> > done
> 
> Sean Hermany schrieb:

---

<div class="post-metadata">

**Author:** ![seanhussey](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@seanhussey](https://www.ruby-forum.com/u/seanhussey)\
**Post date:** [June 6, 2006, 10:17pm UTC](https://www.ruby-forum.com/t/instance-methods-cant-call-protected-class-methods/62632/4 "2006-06-06T22:17:16Z")

</div>

Pete wrote:  
[…]

> protected  
> def self.call\_me  
> puts “static and protected”  
> end  
> […]

Unfortunately, this method is neither “static” nor “protected”.

Although class methods are often used for the same purposes as static  
methods in Java/C++, they are quite a different animal.

And as Sean pointed out, the protected only applies to the methods  
instance methods of Test, not instance methods of Test’s singleton  
class.

– Jim W.

---

<div class="post-metadata">

**Author:** ![seanhussey](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@seanhussey](https://www.ruby-forum.com/u/seanhussey)\
**Post date:** [June 6, 2006, 10:13pm UTC](https://www.ruby-forum.com/t/instance-methods-cant-call-protected-class-methods/62632/5 "2006-06-06T22:13:14Z")

</div>

Sean Hermany wrote:  
[… example elided …]

> Is f not an “object of the defining class”? If so, why should an  
> instance method of Foo not be able to call a protected class method?
> 
> I’m not looking for an answer of the form “because in class scope,  
> self.class.type.object.class # =\> Object, however in _instance_ scope”  
> etc.

So, I’m guessing that saying “Because f and Foo have different defining  
classes” isn’t the answer you are looking for, because you go on to say:

> Logically, why should it be this way?

So you are looking for the reason the protected rule was chosen, rather  
than an explaination of the rule itself.

Hmm, only Matz himself can only answer that question definitively,  
however, I can make some guesses.

The first reason is a complexity/benefit tradeoff. The rule currently  
is that only instances of the same class (or related subclass) can call  
protected methods. Your suggestion would add additional cases to the  
rule. Is the benefit gained from the extra conditions worth the extra  
complexity of the rule? Perhaps not.

There may also be a runtime cost to allowing additional classes to call  
protected methods. Since determining if a protected method call is  
valid involves some runtime checking, making the list of possible  
calling classes larger might impact performance. Note the heavy use of  
“may” and “might” in this paragraph, I’m no expert on Ruby internals.

– Jim W.
