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?

More than 3 years have passed since last update.

Rubyの継承と委譲

Posted at

継承と委譲の使い分けについてあまりわかっていないのでまとめました。

継承

他のクラスから機能を引継ぎ、新たにクラスを作成することです。

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サービスの開発を行っているが、委譲を使う場面があまりない気がします。
今までは何でもかんでも「継承!!」としていた自分がいたのも事実です。
継承関係がいいのか、委譲を使った方がいいのかの判断は難しいですが、今後は委譲を利用するという選択肢も含めた実装をしていこうと思いました。

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