0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

protectedでレシーバ付きでメソッドを呼び出す

Last updated at Posted at 2024-11-21
irb(main):001* class User
irb(main):002*   attr_reader :name
irb(main):003*
irb(main):004*   def initialize(name, weight)
irb(main):005*     @name = name
irb(main):006*     @weight = weight
irb(main):007*   end
irb(main):008*
irb(main):009*   def heavier_than?(other_user)
irb(main):010*     other_user.weight < @weight
irb(main):011*   end
irb(main):012> end
=> :heavier_than?
irb(main):013> alice = User.new("Alice", 50)
=> #<User:0x0000000106eeb658 @name="Alice", @weight=50>
irb(main):014> bob = User.new("BoB",60)
=> #<User:0x0000000106f1bc90 @name="BoB", @weight=60>
irb(main):015> alice.heavier_than?(bob)
(irb):10:in `heavier_than?': undefined method `weight' for #<User:0x0000000106f1bc90 @name="BoB", @weight=60> (NoMethodError)

    other_user.weight < @weight
              ^^^^^^^
...
irb(main):001* class User
irb(main):002*   attr_reader :name, :weight
irb(main):003*
irb(main):004*   def initialize(name, weight)
irb(main):005*     @name = name
irb(main):006*     @weight = weight
irb(main):007*   end
irb(main):008*
irb(main):009*   def heavier_than?(other_user)
irb(main):010*     other_user.weight < @weight
irb(main):011*   end
irb(main):012> end
=> :heavier_than?
irb(main):013> alice = User.new("Alice", 50)
=> #<User:0x00000001085f3e18 @name="Alice", @weight=50>
irb(main):014> bob = User.new("BoB", 60)
=> #<User:0x0000000108572930 @name="BoB", @weight=60>
irb(main):015> alice.heavier_than?(bob)
=> false
  • アクセサメソッドでweightは読み込みできないようになっている

protectedメソッド

外部には公開したくないが、同じクラスやサブクラスの中であればレシーバ付きで呼び出せるようにしたい、という時に登場するのがprotectedメソッドです。

protectedメソッドを試してみる

irb(main):001* class User
irb(main):002*   attr_reader :name
irb(main):003*
irb(main):004*   def initialize(name, weight)
irb(main):005*     @name = name
irb(main):006*     @weight = weight
irb(main):007*   end
irb(main):008*
irb(main):009*   def heavier_than?(other_user)
irb(main):010*     other_user.weight < @weight
irb(main):011*   end
irb(main):012*
irb(main):013*   protected
irb(main):014*
irb(main):015*   def weight
irb(main):016*     @weight
irb(main):017*   end
irb(main):018> end
=> :weight
irb(main):019> alice = User.new("Alice",50)
=> #<User:0x0000000103de9168 @name="Alice", @weight=50>
irb(main):020> bob = User.new("Bob", 60)
=> #<User:0x00000001003c3178 @name="Bob", @weight=60>
irb(main):021> alice.heavier_than?(bob)
=> false
irb(main):022> bob.heavier_than?(alice)
=> true
irb(main):023> alice.weight
(irb):23:in `<main>': protected method `weight' called for #<User:0x0000000103de9168 @name="Alice", @weight=50> (NoMethodError)

alice.weight
     ^^^^^^^

privateメソッドで上のコードを実行する

irb(main):001* class User
irb(main):002*   attr_reader :name
irb(main):003*
irb(main):004*   def initialize(name, weight)
irb(main):005*     @name = name
irb(main):006*     @weight = weight
irb(main):007*   end
irb(main):008*
irb(main):009*   def heavier_than?(other_user)
irb(main):010*     other_user.weight < @weight
irb(main):011*   end
irb(main):012*
irb(main):013*   private
irb(main):014*
irb(main):015*   def weight
irb(main):016*     @weight
irb(main):017*   end
irb(main):018> end
=> :weight
irb(main):019> alice = User.new("Alice",50)
=> #<User:0x000000010fae0a78 @name="Alice", @weight=50>
irb(main):020> bob = User.new("Bob", 60)
=> #<User:0x00000001136d9f48 @name="Bob", @weight=60>
irb(main):021> alice.heavier_than?(bob)
(irb):10:in `heavier_than?': private method `weight called for #<User:0x00000001136d9f48 @name="Bob", @weight=60> (NoMethodError)

    other_user.weight < @weight
              ^^^^^^^

...
irb(main):022> bob.heavier_than?(alice)
(irb):10:in `heavier_than?': private method `weight called for #<User:0x000000010fae0a78 @name="Alice", @weight=50> (NoMethodError)

    other_user.weight < @weight
              ^^^^^^^
...
irb(main):023> alice.weight
(irb):23:in `<main>': private method `weight' called for #<User:0x000000010fae0a78 @name="Alice", @weight=50> (NoMethodError)

alice.weight
     ^^^^^^^
  • privateメソッドweightは読み込めない

特定のメソッドをprotectedに指定する

irb(main):033* class User
irb(main):034*   attr_reader :name, :weight
irb(main):035*   protected :weight
irb(main):036*   def initialize(name, weight)
irb(main):037*     @name = name
irb(main):038*     @weight = weight
irb(main):039*   end
irb(main):040*
irb(main):041*   def heavier_than?(other_user)
irb(main):042*     other_user.weight < @weight
irb(main):043*   end
irb(main):044*
irb(main):045*   def weight
irb(main):046*     @weight
irb(main):047*   end
irb(main):048> end
=> :weight
irb(main):049> alice = User.new("Alice",50)
=> #<User:0x0000000113425ce8 @name="Alice", @weight=50>
irb(main):050> bob = User.new("Bob", 60)
=> #<User:0x00000001134bed30 @name="Bob", @weight=60>
irb(main):051> alice.heavier_than?(bob)
=> false

上のコードをattr_reader :nameにしてみると

irb(main):018* class User
irb(main):019*   attr_reader :name
irb(main):020*   protected :weight
irb(main):021*   def initialize(name, weight)
irb(main):022*     @name = name
irb(main):023*     @weight = weight
irb(main):024*   end
irb(main):025*
irb(main):026*   def heavier_than?(other_user)
irb(main):027*     other_user.weight < @weight
irb(main):028*   end
irb(main):029*
irb(main):030*   def weight
irb(main):031*     @weight
irb(main):032*   end
irb(main):033> end
(irb):20:in `protected': undefined method `weight' for class `User' (NameError)

  protected :weight
  ^^^^^^^^^
  • アクセサメソッドで読み込まれなければprotectedは使えない

attr_writerにすると読み込まれないからエラーになる

irb(main):017* class User
irb(main):018*   attr_writer :name, :weight
irb(main):019*   protected :weight
irb(main):020*   def initialize(name, weight)
irb(main):021*     @name = name
irb(main):022*     @weight = weight
irb(main):023*   end
irb(main):024*
irb(main):025*   def heavier_than?(other_user)
irb(main):026*     other_user.weight < @weight
irb(main):027*   end
irb(main):028*
irb(main):029*   def weight
irb(main):030*     @weight
irb(main):031*   end
irb(main):032> end
(irb):19:in `protected': undefined method `weight' for class `User' (NameError)

  protected :weight
  ^^^^^^^^^
...
irb(main):033* class User
irb(main):034*   attr_reader :name, :weight
irb(main):035*   protected :weight
irb(main):036*   def initialize(name, weight)
irb(main):037*     @name = name
irb(main):038*     @weight = weight
irb(main):039*   end
irb(main):040*
irb(main):041*   def heavier_than?(other_user)
irb(main):042*     other_user.weight < @weight
irb(main):043*   end
irb(main):044*
irb(main):045*   def weight
irb(main):046*     @weight
irb(main):047*   end
irb(main):048> end
=> :lifter: 

感想

アクセサメソッドがおかしいとprotectedでエラーが起こる。
詳しくは理解していない。

weight=が呼び出されるのでprotected :weight=をするとエラーが出ない

irb(main):049* class User
irb(main):050*   attr_writer :name, :weight
irb(main):051*   protected :weight=
irb(main):052*   def initialize(name, weight)
irb(main):053*     @name = name
irb(main):054*     @weight = weight
irb(main):055*   end
irb(main):056*
irb(main):057*   def heavier_than?(other_user)
irb(main):058*     other_user.weight < @weight
irb(main):059*   end
irb(main):060*
irb(main):061*   def weight
irb(main):062*     @weight
irb(main):063*   end
irb(main):064> end
=> :weight
0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?