継承と委譲の使い分けについてあまりわかっていないのでまとめました。
継承
他のクラスから機能を引継ぎ、新たにクラスを作成することです。
例
Baseクラスからすべのたメソッドを引継ぎ、Fooクラスを作成する
class Base
def message
'ok'
end
end
class Foo < Base; end
foo = Foo.new
puts foo.message
# => ok
委譲
特定の処理(責任)を他のクラスのメソッドに委ねることです。
例
BaseクラスのmessageメソッドをFooクラスにmessageメソッドを委ねる
class Base
def message
'ok'
end
end
require 'forwardable'
class Foo
extend Forwardable
attr_reader :mess
def initialize
@mess = Base.new
end
def_delegator :mess, :message
end
foo = Foo.new
puts foo.message
# => ok
継承を使う場面
役割が同じ
駆け出しエンジニアも、経験が豊富なつよつよエンジニアも、プログラマーという役割は一緒です。
なので、Progurammerクラスを継承し、機能をそのまま引き継ぐようにします。
class Programmer
def initialize(type, langages)
@type = type
@langages = Array(langages)
end
def type_is
puts "私は#{type}です。"
end
def langage_is
str = ''
langages.each do |lang|
str += "#{lang} "
end
puts "私は#{str}の言語を扱えます"
end
def klass_is
str = case self.class.name
when 'TsuyoTsuyo'
'強強エンジニア'
when 'Kakedashi'
'駆け出しエンジニア'
end
puts "私は#{str}です。"
end
private
attr_accessor :type, :langages
end
class TsuyoTsuyo < Programmer; end
class Kakedashi < Programmer; end
tsuyo = TsuyoTsuyo.new('Backend', %w[C C++ Python Go Ruby])
tsuyo.type_is
tsuyo.langage_is
tsuyo.klass_is
kake = Kakedashi.new('Frontend', %w[HTML CSS jQuery])
kake.type_is
kake.langage_is
kake.klass_is
委譲を使う場面
役割は異なるが一部の機能を使いたい
プログラマーとデザイナーでは役割が異なります。なのでこの場合は委譲を使い、type_is
メソッドのみをProgrammerクラスより譲り受けるようにします。
require 'forwardable'
class Programmer
def initialize(type, langages)
@type = type
@langages = Array(langages)
end
def type_is
puts "私は#{type}です。"
end
private
attr_accessor :type, :langages
end
class Designer
extend Forwardable
def initialize(type, skills)
@programmer = Programmer.new(type, nil)
@type = type
@skills = Array(skills)
end
def_delegator :@programmer, :type_is
private
attr_accessor :type, :skills
end
class IkeIke < Designer; end
ikeike = IkeIke.new('WebDesigner', %w[HTML CSS Adobe JavaScript])
ikeike.type_is # このtype_isメソッドは`Programmer` classから譲り受けたメソッド
まとめ
ここまでお読みいただきありがとうございます。
自分のコードを見直す機会になればと思います。
自分は普段はRailsでwebサービスの開発を行っているが、委譲を使う場面があまりない気がします。
今までは何でもかんでも「継承!!」としていた自分がいたのも事実です。
継承関係がいいのか、委譲を使った方がいいのかの判断は難しいですが、今後は委譲を利用するという選択肢も含めた実装をしていこうと思いました。