ruby three Ps 実験 その1

ここまで読んでも全然わかんない orz
http://d.hatena.ne.jp/toshi_hirasawa/20130122/1358841378

よって、実験することにする

[hirasawa@centos-hira ~]$ cat threePs.rb
#!/usr/local/bin/ruby -Ku
class AccessTest
    public
    def publ
        p(self)
        puts "public_method"
        self.prot
        #self.priv  # error!!
        prot
        priv
    end

    protected
    def prot
        p(self)
        puts "protected_method"
    end

    private
    def priv
        p(self)
        puts "private_method"
    end
end

class SubAccessTest < AccessTest
    def publ_s
        publ
    end

    def prot_s
        prot
    end

    def priv_s
        priv
    end
end

at = SubAccessTest.new()
at.publ
#at.prot   #  error! prptected method "prot" called for #<SubAccessTest:xxxx>
#at.priv   #  error! private method "priv" called fof #<SubAccessTest:xxxx>

sat = SubAccessTest.new()
sat.publ_s
sat.prot_s  # no error!
sat.priv_s  # no error!

結果を以下にしめす

[hirasawa@centos-hira ~]$ ./threePs.rb
#<SubAccessTest:0x9fbf4c4>
public_method
#<SubAccessTest:0x9fbf4c4>
protected_method
#<SubAccessTest:0x9fbf4c4>
protected_method
#<SubAccessTest:0x9fbf4c4>
private_method
#<SubAccessTest:0x9fbf3fc>
public_method
#<SubAccessTest:0x9fbf3fc>
protected_method
#<SubAccessTest:0x9fbf3fc>
protected_method
#<SubAccessTest:0x9fbf3fc>
private_method
#<SubAccessTest:0x9fbf3fc>
protected_method
#<SubAccessTest:0x9fbf3fc>
private_method
[hirasawa@centos-hira ~]$


まずは、private/protectedのみにターゲットを絞ってもうちょい突っ込んで確認。
つぎのコードをベースに実験

[hirasawa@centos-hira ~]$ cat private.rb
#!/usr/local/bin/ruby -Ku
class Main
    #protected      #################################
    #private        #################################
    def priv
        puts "private_method"
    end

    public
    def call_priv_from_main
        self.priv

    end
    def show
        p "show part in main"
    end
end

class Sub < Main
    def call_priv_from_sub
        self.priv
    end
    def show
        p "show part in sub"
    end
end

Main.new().show
Sub.new().show
Main.new().call_priv_from_main
Sub.new().call_priv_from_sub
Sub.new().call_priv_from_main
[hirasawa@centos-hira ~]$
[hirasawa@centos-hira ~]$ ./private.rb
"show part in main"
"show part in sub"
private_method
private_method
private_method
[hirasawa@centos-hira ~]$

最初はprotectedもprivateもコメントアウトされている状態(つまりpublic)
なのでふつうに動く

つづいて、#protectedの コメントだけをはずしてみると
これも動く

最後に #privateのコメントだけを外してみると

[hirasawa@centos-hira ~]$ ./private.rb
"show part in main"
"show part in sub"
./private.rb:11:in `call_priv_from_main': private method `priv' called for #<Main:0xa1498a8> (NoMethodError)
        from ./private.rb:30:in `<main>'
[hirasawa@centos-hira ~]$

ほほう、
ここまでわかったことのまとめ

  • public

そのメソッドが定義されたクラス内、サブクラス、クラス外(インスタンス)のどこからでもアクセス可

public に設定されたメソッドは制限なしに呼び出し可

  • private

メソッドは、クラスの内部(定義クラスとサブクラス)からのみアクセス可
レシーバを指定して呼び出すのは不可で、クラス内部からでもインスタンスメソッドとしては使えない。

private に設定されたメソッドは関数形式でしか呼び出せません



以下、ruby本家(の近くか?)で見つけたFAQ

http://www.ruby-lang.org/ja/old-man/html/FAQ_A5E1A5BDA5C3A5C9.html#a5.2e5.20private.a4.c8protected.a4.ce.b0.e3.a4.a4.a4.ac.ca.ac.a4.ab.a4.ea.a4.de.a4.bb.a4.f3

privateの意味は、メソッドを関数形式でだけ呼び出せるようにし、 レシーバー形式では呼び出せないようにするという意味です。したがって、 可視性がprivateなメソッドは、自クラス及びサブクラスからしか参照 できません。



protectedも同様に、自クラス及びサブクラスからしか参照できませんが、 関数形式でもレシーバー形式でも呼び出せます。

メソッドのカプセル化に必要な機能です。

  • protected

メソッドは、クラスの内部(定義クラスとサブクラス)からのみアクセス可
レシーバを指定して呼び出すことができ、クラス内部からであればインスタンスメソッドとして使える。

protected に設定されたメソッドは、そのメソッドを持つオブジェクトが selfであるコンテキスト(メソッド定義式やinstance_eval)でのみ呼び出せ ます。





うう、でもまだよく咀嚼できていないような気満々なので、(きっと)つづく