オブジェクト指向設計におけるコンポジションの活用法とそのメリット
# エンジンクラス class Engine def start puts 'エンジンが始動しました!' end def stop puts 'エンジンが停止しました!' end end
# 車クラス(Car)はエンジンクラス(Engine)のインスタンスを内部に持つ class Car def initialize # Engineクラスのインスタンスを生成して内部に保持する @engine = Engine.new end def start_car puts '車を動かします。' @engine.start end def stop_car puts '車を止めます。' @engine.stop end end
my_car = Car.new my_car.start_car # 出力: # 車を動かします。 # エンジンが始動しました! my_car.stop_car # 出力: # 車を止めます。 # エンジンが停止しました!
# 悪い例:継承の誤用 class Engine def start puts 'エンジンが始動しました!' end def stop puts 'エンジンが停止しました!' end end # 車はエンジンではないのに、エンジンを継承している class Car < Engine def drive puts '車を運転します' start # 継承したメソッド end end # この設計の問題点: # 1. 意味的に不自然(車はエンジンではない) # 2. エンジンを変更できない(電気エンジンに交換不可) # 3. 複数のコンポーネントを持てない(タイヤやブレーキを追加できない)
# 電気エンジンのクラス class ElectricEngine def start puts '電気エンジンが静かに始動しました!' end def stop puts '電気エンジンが停止しました!' end end # エンジンを交換できるようにする class Car def initialize(engine) @engine = engine end def start_car puts '車を動かします。' @engine.start end def stop_car puts '車を止めます。' @engine.stop end end # 通常エンジンの車 normal_car = Car.new(Engine.new) normal_car.start_car # 車を動かします。 # エンジンが始動しました! # 電気エンジンの車 electric_car = Car.new(ElectricEngine.new) electric_car.start_car # 車を動かします。 # 電気エンジンが静かに始動しました!
# タイヤクラス class Tire attr_reader :size, :type def initialize(size, type) @size = size @type = type end def info "#{@size}インチ #{@type}タイヤ" end end # ブレーキクラス class Brake attr_reader :type def initialize(type) @type = type end def apply puts "#{@type}ブレーキをかけました!" end end # GPSナビゲーションクラス class Navigation def calculate_route(destination) puts "#{destination}への最適ルートを計算中..." sleep(1) puts "ルートが見つかりました!" end end # 拡張された車クラス class AdvancedCar def initialize(engine, tire_size: 17, tire_type: 'ラジアル', brake_type: 'ディスク') @engine = engine @tires = Array.new(4) { Tire.new(tire_size, tire_type) } @brake = Brake.new(brake_type) @navigation = Navigation.new end def start puts "車の準備を開始します..." puts "タイヤ: #{@tires.first.info} x 4本" puts "ブレーキ: #{@brake.type}" @engine.start end def stop @brake.apply @engine.stop end def navigate_to(destination) @navigation.calculate_route(destination) end end # 使用例 my_car = AdvancedCar.new( ElectricEngine.new, tire_size: 18, tire_type: 'スポーツ', brake_type: 'カーボン' ) my_car.start my_car.navigate_to("東京駅") my_car.stop
Computer
info
show_specs