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