クラスは、拡張に対してはオープンで、変更に対してはクローズである必要があるというオープン/クローズド プリンシパルについてよく耳にします。抽象的なレベルで素晴らしいですね。
しかし、Ruby OOP の世界で実際に使用されている例はありますか?
クラスは、拡張に対してはオープンで、変更に対してはクローズである必要があるというオープン/クローズド プリンシパルについてよく耳にします。抽象的なレベルで素晴らしいですね。
しかし、Ruby OOP の世界で実際に使用されている例はありますか?
Ruby クラスはすべて公開されています。クローズドクラスはありません。
例:
class String
def foo
puts "bar"
end
end
'anything'.foo
#bar
オープン/クローズの原則は、Ruby にも当てはまります。
定義によると..クラス/オブジェクトは拡張用に開いている必要がありますが、変更用には閉じている必要があります。どういう意味ですか?
これは、クラスを変更して新しい動作を追加するべきではないことを意味します。継承または合成を使用してそれを達成する必要があります。
例えば
class Modem
HAYES = 1
COURRIER = 2
ERNIE = 3
end
class Hayes
attr_reader :modem_type
def initialize
@modem_type = Modem::HAYES
end
end
class Courrier
attr_reader :modem_type
def initialize
@modem_type = Modem::COURRIER
end
end
class Ernie
attr_reader :modem_type
def initialize
@modem_type = Modem::ERNIE
end
end
class ModemLogOn
def log_on(modem, phone_number, username, password)
if (modem.modem_type == Modem::HAYES)
dial_hayes(modem, phone_number, username, password)
elsif (modem.modem_type == Modem::COURRIER)
dial_courrier(modem, phone_number, username, password)
elsif (modem.modem_type == Modem::ERNIE)
dial_ernie(modem, phone_number, username, password)
end
end
def dial_hayes(modem, phone_number, username, password)
puts modem.modem_type
# implmentation
end
def dial_courrier(modem, phone_number, username, password)
puts modem.modem_type
# implmentation
end
def dial_ernie(modem, phone_number, username, password)
puts modem.modem_type
# implementation
end
end
新しいタイプのモデムをサポートするには、クラスを変更する必要があります。
継承の使用。モデム機能を抽象化できます。と
# Abstration
class Modem
def dial
end
def send
end
def receive
end
def hangup
end
end
class Hayes < Modem
# Implements methods
end
class Courrier < Modem
# Implements methods
end
class Ernie < Modem
# Implements methods
end
class ModelLogON
def log_on(modem, phone_number, username, password)
modem.dial(phone_number, username, password)
end
end
新しいタイプのモデムをサポートするために、ソース コードを変更する必要はありません。新しいコードを追加して、新しいタイプのモデムを追加できます。
これが、継承を使用してオープン/クローズの原則を実現する方法です。この原理は、他の多くの手法を使用して実現できます。