LoginSignup
0
0

More than 1 year has passed since last update.

[py2rb] 多重継承の3

Posted at

はじめに

移植やってます。
( from python 3.7 to ruby 2.7 )

多重継承 (Python)

移植するにあたり、多重継承はRubyミックスインで行こうと思っていました。
__init__のないクラスをモジュールにする予定でしたが、これでは避けられないようですので、委譲により多重継承を表現できればと思います。

forwardable (Ruby)

require 'forwardable'

class A
  def initialize(s)
    @s = s
  end

  def putsa(o)
    puts "#{@s}#{o}です"
  end

  def putsd()
    puts "呼び出されたクラスは#{self.class}です"
  end
end

class B
  def initialize(s)
    @s = s
  end

  def putsb(o)
    puts "#{@s}#{o}です"
  end

  def putsd()
    puts "呼び出されたクラスは#{self.class}です"
  end
end

class C
  extend Forwardable

  def initialize(*args, **kwargs)
    @a = A.new(kwargs['A'])
    @b = B.new(kwargs['B'])
  end

  def_delegators :@a, :putsa, :putsd
  def_delegators :@b, :putsb, :putsd
end

c = C.new('A' => '好きな食べ物', 'B' => '好きな飲み物')
c.putsa('みかん')
c.putsb('コーヒー')
c.putsd()

p C.ancestors

# output
好きな食べ物はみかんです
好きな飲み物はコーヒーです      
呼び出されたクラスはBです       
[C, Object, Kernel, BasicObject]

学習したばかりのforwardableを使用した例です。
メソッドが重複した場合、後のdef_delegators :@b, :putsb, :putsdが優先されるようです。
また、ancestorsにクラスABも検索されませんので、superで呼び出したりとかはできないものと思われます。

delegate (Ruby)

require 'delegate'

class A
  def initialize(s)
    @s = s
  end

  def putsa(o)
    puts "#{@s}#{o}です"
  end

  def putsd()
    puts "呼び出されたクラスは#{self.class}です"
  end
end

class B
  def initialize(s)
    @s = s
  end

  def putsb(o)
    puts "#{@s}#{o}です"
  end

  def putsd()
    puts "呼び出されたクラスは#{self.class}です"
  end
end

class C
  def initialize(*args, **kwargs)
    @a = SimpleDelegator.new(A).new(kwargs['A'])
    @b = SimpleDelegator.new(B).new(kwargs['B'])
  end

  def method_missing(name, *args)
    [@b, @a].each do |x|
      if x.respond_to?(name)
        return x.method(name).call(*args)
      end
    end
    raise "メソッド #{name} が見つかりません"
  end
end

c = C.new('A' => '好きな食べ物', 'B' => '好きな飲み物')
c.putsa('みかん')
c.putsb('コーヒー')
c.putsd()

p C.ancestors

# output
好きな食べ物はみかんです
好きな飲み物はコーヒーです      
呼び出されたクラスはBです       
[C, Object, Kernel, BasicObject]

もう一つのdeletagorを使用した例です。
メソッド数が多い場合は、こちらの方が楽かもしれません。

メモ

  • Python の 多重継承の3 を学習した
  • 百里を行く者は九十里を半ばとす
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