give IT a try

プログラミング、リモートワーク、田舎暮らし、音楽、etc.

Rubyのクラスメソッドは同じクラスのprotectedメソッドやprivateメソッドにアクセスできない

C#JavaプログラマRubyの世界にやってくると「あれれ?」と思ってしまう言語仕様をまた見つけてしまいました。
タイトルにも書いた通り、Rubyのクラスメソッドは同じクラスのprotectedメソッドやprivateメソッドにアクセスできません。


言葉だけではピンと来ないと思うので、サンプルコードを見てみましょう。
まずはC#のコードから。これは正常に動作します。

using System;
public class MainClass
{
    public static void Main()
    {
        Hoge.ClassMethod();
    }
}

public class Hoge
{
    public static void ClassMethod()
    {
        var hoge = new Hoge();
        Console.WriteLine(hoge.PublicMethod());
        Console.WriteLine(hoge.ProtectedMethod());
        Console.WriteLine(hoge.PrivateMethod());
    }

    public string PublicMethod()
    {
        return "public";
    }

    protected string ProtectedMethod()
    {
        return "protected";
    }

    private string PrivateMethod()
    {
        return "private";
    }
}


実行結果

public
protected
private


つまりC#の場合、同じクラスであればprotectedであれ、privateであれ、どのメソッドも呼び出せます。
これはJavaも同じはずです。


これとほぼ同等のコードをRubyで書いてみます。
すると・・・

class Hoge
 def self.class_method
   hoge = Hoge.new
   puts_safe {hoge.public_method}
   puts_safe {hoge.protected_method}
   puts_safe {hoge.private_method}
 end

 def public_method
   "public"
 end

 protected
 def protected_method
   "protected"
 end

 private
 def private_method
   "private"
 end
end

def puts_safe
 puts yield
rescue => e
 puts "ERROR!! - #{e}"
end

Hoge.class_method


実行結果

public
ERROR!! - protected method `protected_method' called for #<Hoge:0x869cd98>
ERROR!! - private method `private_method' called for #<Hoge:0x869cd98>


C#とは異なり、protectedとprivateのインスタンスメソッドを呼び出すとエラーが発生しました。


Rubyのprivateメソッドはレシーバ経由で呼び出せないということは知っていたので、privateメソッドでエラーが出るのは分かるのですが、protectedメソッドでもエラーが起きるのはちょっと予想外でした。
とはいえ、C#Javaとは誕生の経緯や設計の思想も違うので、C#Javaの常識が通用しない点が出てくるのは以前のエントリにも書いた通りです。


今後もC#JavaからRubyへ転向してきたプログラマがつまずきそうなポイントを見つけたら、またこのブログでご紹介しますね。

あわせて読みたい

JavaやC#の常識が通用しないRubyのprivateメソッド - give IT a try
以前はオブジェクト指向言語ならどれも同じだろうと思っていたので、この言語仕様を知った時はかなり驚きました。
Matz先生自身にRuby設計思想を教えてもらったので、大変勉強になりました。