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の設計思想を教えてもらったので、大変勉強になりました。