##カプセル化
オブジェクト同士の紐付き(関係性)を薄くし、独立性を高め、再利用や交換といった保守性を高める効率の考え方。
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>
##参考