🕌

オブジェクト指向型と関数型のポリモーフィズムの記述の違い

2023/08/24に公開

オブジェクト指向でなぜつくるのかに関数型プログラミングの場合、ポリモーフィズムの仕組みをオブジェクト指向プログラミングよりシンプルに実現できると記載があったが具体例がなかったので、どちらのスタイルでも記述できるRubyで書いてみて、違いを確認する。

関数型プログラミング

def square(x)
  x * x
end

def double(x)
  x * 2
end

def transform_array(fn, arr)
  arr.map { |x| fn.call(x) } # 挙動は与えられるfnによって変わる→ポリモーフィズム
end

numbers = [1, 2, 3, 4]

squared = transform_array(method(:square), numbers) # 第一引数として関数を渡している
doubled = transform_array(method(:double), numbers) # 第一引数として別の関数を渡している

puts squared.inspect  # 出力: [1, 4, 9, 16]
puts doubled.inspect  # 出力: [2, 4, 6, 8]

オブジェクト指向型プログラミング

class Function
  def apply(x)
    raise "Not implemented"
  end

  def transform_array(arr)
    arr.map { |x| apply(x) }  # 挙動はサブクラスのapplyの実装によって変わる→ポリモーフィズム
  end
end

class SquareFunction < Function
  def apply(x)
    x * x
  end
end

class DoubleFunction < Function
  def apply(x)
    x * 2
  end
end

numbers = [1, 2, 3, 4]

square_function = SquareFunction.new # サブクラスの初期化
squared = square_function.transform_array(numbers)

double_function = DoubleFunction.new # 別のサブクラスの初期化
doubled = double_function.transform_array(numbers)

puts squared.inspect  # 出力: [1, 4, 9, 16]
puts doubled.inspect  # 出力: [2, 4, 6, 8]

注意点

今回はあくまで二つの違いを強調するためのコードであり、どちらよりもシンプルに書く方法も存在する。

squared = [1, 2, 3, 4].map { |x| x * x }
doubled = [1, 2, 3, 4].map { |x| x * 2 }

Discussion