権限の種類
public
... どこからでもアクセス可能。クラス内にメソッドを定義した際のデフォルトのアクセス権protected
... そのクラスまたはサブクラスのインスタンスメソッドからしか呼び出すことができないprivate
... レシーバーの省略形でしか呼び出すことができない (self
に対してしか呼び出すことができない)
権限の設定方法
public
,protected
,private` のキーワードに続けてメソッド名を文字列またはシンボルで引き渡す
※ 先にメソッドが定義されている必要がある- 引数なしの
public
,protected
,private` キーワードを置くと、それ以降のメソッドはその権限になる
class MyClass # デフォルトでは public メソッド def public_method p 'public' end protected # これより下は protected になる def protected_method p 'protected' end private # これより下は private になる def private_method p 'private' end def call_protected_method protected_method end def call_private_method private_method end # public メソッドに指定 public :call_protected_method, :call_private_method end c = MyClass.new c.public_method # => "public" # protected メソッドは外部から直接呼び出すことはできない c.protected_method # => NoMethodError protected method `protected_method' called # private メソッドも外部から直接呼び出すことはできない c.private_method # => NoMethodError private method `private_method' called c.call_protected_method # => "protected" c.call_private_method # => "private"
Protected と Private 権限の違い
protected
はメソッドが定義されているクラスと、そのサブクラスのインスタンスメソッドから呼び出すことができる
private
は self
に対してのみ呼び出しが可能、つまり同じクラスのオブジェクトでも他のオブジェクトの持つ private メソッドは呼び出すことができない
Protected
class ClassPermission attr_reader :name def initialize(name) @name = name end def use_protected(recever = self) print "#{@name} call #{recever.name}.protected_method > " recever.protected_method end protected def protected_method p 'protected' end end # サブクラス class SubClassPermission < ClassPermission end c1 = ClassPermission.new('C1') c2 = ClassPermission.new('C2') cSub = SubClassPermission.new('SubClass') # 自身をレシーバーにじて protected メソッドを実行できる c1.use_protected(c1) # => C1 call C1.protected_method > "protected" # 同じクラスインスタンスからレシーバーを通じて protected メソッドを実行できる c2.use_protected(c1) # => C2 call C2.protected_method > "protected" # サブクラスのインスタンスからレシーバーを通じて protected メソッドを実行できる cSub.use_protected(c1) # => SubClass call C1.protected_method > "protected"
無関係なクラスインスタンスのメソッド内からはレシーバーを通じても呼び出すことはできない
class Hoo def use_protected(recever = self) puts "Hoo call #{recever.name}.protected_method" recever.protected_method rescue => e p e end end hoo = Hoo.new hoo.use_protected(c1) # => Hoo call C1.protected_method # => NoMethodError: protected method `protected_method' called
Private
class ClassPermission attr_reader :name def initialize(name) @name = name end def call_private print "#{@name} call private_method > " private_method end def use_private(recever = self) puts "#{@name} call #{recever.name}.private_method > " recever.private_method end def call_recever_call_private(recever = self) puts "#{@name} call #{recever.name}.call_private >> " recever.call_private end private def private_method p 'private' end end c1 = ClassPermission.new('C1') c2 = ClassPermission.new('C2') class SubClassPermission < ClassPermission end c1.call_private # => C1 call private_method > "private" # private メソッドは self の省略形でしか呼び出すことができない c1.use_private # => C1 call C1.private_method > # => NoMethodError: private method `private_method' called # 当然他のクラスインタンスからレシーバーを通じて呼び出そうとしてもエラー c2.use_private(c1) # => C2 call C1.private_method > # => NoMethodError: private method `private_method' called # レシーバー自身の private メソッドを使っているメソッドを呼び出すのはOK c1.call_recever_call_private(c1) # => C1 call C1.call_private > # => C1 call private_method > "private" c2.call_recever_call_private(c1) # => C2 call C1.call_private >> # => C1 call private_method > "private" # サブクラスからでもOK cSub.call_recever_call_private(c1) # => SubClass call C1.call_private >> # => C1 call private_method > "private"
private メソッドを呼び出しているメソッドが public メソッドなら無関係なクラスからでも呼び出せる
class Hoo def call_recever_call_private(recever = self) puts "Hoo call #{recever.name}.call_private >> " recever.call_private end end hoo = Hoo.new hoo.call_recever_call_private(c1) # => Hoo call C1.call_private >> # => C1 call private_method > "private"
private メソッドを呼び出しているメソッドが protected なら無関係のクラスのインスタンスメソッドからは呼び出せなくなる
class ClassPermission attr_reader :name def initialize(name) @name = name end protected def call_private print "#{@name} call private_method > " private_method end private def private_method p 'private' end end class Hoo def call_protected_recever_call_private(recever = self) puts "Hoo call #{recever.name}.call_private >> " recever.call_private rescue => e p e end end c1 = ClassPermission.new('c1') hoo = Hoo.new hoo.call_protected_recever_call_private(c1) # => Hoo call c1.call_private >> # => NoMethodError: protected method `call_private' called
まとめ
Ruby のクラスインスタンスメソッドの権限は public
, protected
, private
があり、設定方法は2種類ある。
最もアクセス権が厳しいのが private
で自身(self
)からしか呼び出すことができない
protected
は同じクラスのインスタンスだけでなく、子孫クラスのインスタンスメソッドからも呼び出すことができる
- 作者: まつもとゆきひろ,David Flanagan,卜部昌平(監訳),長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2009/01/26
- メディア: 大型本
- 購入: 21人 クリック: 356回
- この商品を含むブログ (129件) を見る