LoginSignup
1
0

More than 1 year has passed since last update.

【オブジェクト指向】カプセル化

Last updated at Posted at 2021-11-30

カプセル化

オブジェクト同士の紐付き(関係性)を薄くし、独立性を高め、再利用や交換といった保守性を高める効率の考え方。

class Foo
  def initialize(foo='foo', bar='bar')
     @foo = foo
     @bar = bar
  end  
end  

f = Foo.new
f.foo
#=> NoMethodError: undefined method `foo' for #<Foo:0x0000562351fbab60 @foo="foo", @bar="bar">
  • attr_accessor :foo, :barと書くだけでインスタンス変数@foo@barにアクセスできるように
class Foo
  attr_accessor :foo, :bar
  def initialize(foo='foo', bar='bar')
     @foo = foo
     @bar = bar
  end  
end

f = Foo.new
f.foo
#=> "foo"
f.bar
#=> "bar"

attr_accessorメソッドを使って書くと

メソッドの呼び出し時に毎回変数を書かなくてよい。

class Square
  attr_accessor :height, :width
  def initialize(height, width)
    @height = height
    @width = width
  end

  # 面積計算
  def calc_area
    height * width
  end

  # 正方形の時trueになる
  def square?
    height == width
  end
end

sq = Square.new(20, 30)
sq.square?
#=> false
sq.height = 30
#=> 30
sq.calc_area
#=> 900
sq.square?
#=> true

attr_accessorメソッドを使わずに書くと

メソッドを呼び出すときに毎回変数が必要になる。
メソッドに新たな変数を加える変更をしたいときに全メソッドに変数を付け加えなければならない。
カプセル化でオブジェクト同士の独立性を高めてコードを管理しやすくする。

class Square
  # 面積計算
  def calc_area(height, width)
    height * width
  end

  # 正方形の時trueになる
  def square?(height, width)
    height == width
  end
end

sq = Square.new
sq.square?(20, 30)
#=> false
sq.calc_area(30, 30)
#=> 900
sq.square?(30, 30)
#=> true

おまけ

heightとwidthを更新することを考えたらこういう実装がより使えるらしい。
(弊社CTOありがとうございます!)

class Square
  attr_reader :height, :width

  def initialize(opts = {})
    update(opts)
  end

  def update(opts = {})
    @height = opts[:height] if opts.key?(:height)
    @width = opts[:width] if opts.key?(:width)
  end

  def calc_area
    height * width
  end

  def square?
    height == width
  end
end

sq = Square.new(height: 30, width: 20)
=> #<Square:0x000055557fb27198 @height=30, @width=20>
sq.calc_area
#=> 600
sq.square?
#=> false
sq.update(height: 70, width: 70)
#=> 70
sq.calc_area
#=> 4900
sq.square?
#=> true

ちなみに

上のおまけ実装でheightをupdateしたときはnilが返り、widthをupdateしたときはsq.widthの結果が返る。

sq.update(height: 40)
#=> nil
sq.update(width: 40)
#=> 40

heightをupdateしたとき、widthの条件文if opts.key?(:width)に当てはまらず返り値がnilになっている。

def update(opts = {})
  @height = opts[:height] if opts.key?(:height)
  @width = opts[:width] if opts.key?(:width)
end

最後にselfを返すようにしたらオブジェクトが返る。

def update(opts = {})
  @height = opts[:height] if opts.key?(:height)
  @width = opts[:width] if opts.key?(:width)
  self
end

sq.update(height:30)
=> #<Square:0x000055ff79c97178 @height=30, @width=30>
sq.update(width:40)
=> #<Square:0x000055ff79c97178 @height=30, @width=40>

参考

1
0
0

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
1
0