徒然なるままに

個人の備忘録を中心としたブログです

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

クラスのインスタンスメソッドは何も指定がない場合、全てpublicメソッドになる。
例外的にinitializeメソッドだけは暗黙的にprivateメソッドになるが、
その他のインスタンスメソッドは可視性(public,private,protected)を指定することができる。

一方、クラスのインスタンス変数の可視性(public,private,protected)は指定できず、暗黙的に全てprivateになる。
これはオブジェクトのカプセル化概念を強固にするためのRubyの仕様である。

publicメソッドは、クラス定義内、クラス定義外(クラスのオブジェクトを生成して使用する側)のどちらからでも呼び出せる。
privateメソッドは、クラス定義内でのみ呼び出すことができ、呼び出すときはprivate_method(任意の引数個数)という関数のような形で呼び出さなければならない。self.private_method()とは書くことができない。
protectedメソッドは、そのクラスの定義内、またはそのクラスの全てのサブクラスの定義内からのみ呼び出すことができる。こちらもprotected_method()という関数のような形式で呼び出さなければならない。



インスタンスメソッドの可視性の指定の方法は二通りある。
1、インスタンスメソッド定義の前に何もつけない(public)、protected、privateを宣言(*注 正確な表現ではない。詳細は後述)する方法。
2、インスタンスメソッドの定義の後、protected、privateにインスタンスメソッド名のシンボルを渡す方法。



1、インスタンスメソッド定義の前に何もつけない(public)、protected、privateを宣言(*注 正確な表現ではない。詳細は後述)する方法

コードを分かりやすく説明するために、protected、privateを「宣言」すると書いたが
これは正しくない。実際のところprotected、privateはObjectクラスのprivateメソッドであり、
後に続く複数のインスタンスメソッドの定義を引数にとるものになっている。


class MyClass
# 事前に何も指定がない場合はpublicメソッド
def public_method
puts "public_method"
end

def X # この@xアクセッサもパブリックメソッド
@x # xはnilである
end

# ここに任意の数のpublicメソッドを定義できる

protected # このprotected宣言(実際はprotectedはObjectのインスタンスメソッド)はprivate宣言まで有効
def protected_method
puts "protected_method"
end

# ここに任意の数のprotectedメソッドを定義できる

private # このprivate宣言(実際はprivateはObjectのインスタンスメソッド)はクラス定義の最後まで有効
def private_method
puts "private_method"
end

#ここに任意の数のprivateメソッドを定義できる

end

c = MyClass.new
c.public_method #=> "public_method"と表示
c.protected_method #=> エラー
c.private_method #=> エラー


2、インスタンスメソッドの定義の後にprotected、privateにインスタンスメソッド名のシンボルを渡す方法。

1で述べたようにprotected、privateの両者はObjectのprivateメソッドであり、これらはメソッド名のシンボルを複数引数に取ることができる。


class MyClass

def public_method
puts "public_method"
end

def X #この@xアクセッサもパブリックメソッド
@x
end

def protected_method
puts "protected_method"
end
protected :protected_method

def private_method
puts "private_method"
end
private :private_method

end




このようにprivate、protectedされたメソッドでもRubyのメタプログラミング機能によりアクセスすることができる。
メタとは「~を越えた」という意味をもつ言葉で、プログラミングを越えた強力な機能であるから使用には注意を要する。
通常は、この機能を使わないようにプログラムを設計するのが正しい。

sendメソッドは任意のオブジェクトのインスタンスメソッド名のシンボルを渡すことで、そのインスタンスメソッドにアクセスすることができる。
instance_evalはブロック内で評価を行うことでインスタンスメソッドにアクセスできる。instance_evalはカプセル化されたインスタンス変数にもアクセスすることができる。

c = MyClass.new
c.send :private_method
c.instance_eval {public_method}
c.instance_eval {@x}

コメント

コメントの投稿

管理者にだけ表示を許可する

トラックバック

http://kamiyasu2.blog.fc2.com/tb.php/37-718b1528

kamiyasu

Author:kamiyasu

QR

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。