Liskov Substitution Principle (Liskov Yerine Geçme Prensibi)¶
3. Liskov Substitution Principle¶
- LSP, bir üst sınıfın nesnelerinin, programın doğruluğunu etkilemeden kendi alt sınıflarının nesneleriyle değiştirilebilmesi gerektiğini belirten, nesne yönelimli programlamada bir ilkedir.
- Başka bir deyişle, alt sınıflar, temel sınıflarıyla birbirinin yerine kullanılabilir olmalıdır.
- Bu standart takip edildiğinde kod daha iyi anlaşılır, test edilebilir ve sürdürülebilir olmaktadır.
- Ödeme sistemi örneği üzerinden LSP'yi görelim.
3.1. LSP ihlal¶
class PaymentProcessor:
def process_payment(self, payment: Payment, security_code):
# odeme islemleri sureci
payment.make_payment(security_code)
class Payment:
def make_payment(self, security_code):
# Genel/ortak ödeme işlemleri
print(f"Verifying security code: {security_code}")
class CreditCardPayment(Payment):
def make_payment(self, security_code):
# Kredi kartına özel ödeme işlemleri
print("Processing credit card payment")
print(f"Verifying security code: {security_code}")
class PayPalPayment(Payment):
def make_payment(self, security_code):
# PayPal özel ödeme işlemleri
print("Processing PayPal payment")
# PayPal security_code yerine email adresi ile doğrulama kabul ediyor.
# Payment temel sınıfından farklı davranış sergiliyor.
print(f"Verifying email: {security_code}")
payment_processor = PaymentProcessor()
# Mevcut fonksiyonelite ile kredi kartı ödeme işlemi
credit_card_payment = CreditCardPayment()
payment_processor.process_payment(credit_card_payment, "1234")
# PayPal ile ödeme işlemi (LSP ihlali) Neden?
# Çünkü temel sınıf(base class) security_code ile çalışıyor. Tutarsızlık oluşmakta!
paypal_payment = PayPalPayment()
payment_processor.process_payment(paypal_payment, "client@example.com")
PayPalPayment alt sınıfı, güvenlik kodu yerine bir e-posta adresini (güvenlik_kodu) kabul ederek make_payment yönteminin davranışını değiştirdiği için LSP'yi ihlal eder. Davranıştaki bu tutarsızlık, security_code parametresinin Payment'ın tüm alt sınıflarında aynı anlama ve kullanıma sahip olduğunu varsaydığından ilkeyi bozar.
3.2. LSP uygulama¶
class PaymentProcessor:
def process_payment(self, payment: Payment):
# odeme islemleri sureci
payment.make_payment()
class Payment:
def make_payment(self):
# Genel/ortak ödeme işlemleri
class CreditCardPayment(Payment):
def __init__(self, security_code):
self.security_code = security_code
def make_payment(self):
# Kredi kartına özel ödeme işlemleri
print("Processing credit card payment")
print(f"Verifying security code: {self.security_code}")
class PayPalPayment(Payment):
def __init__(self, email):
self.email = email
def make_payment(self):
# PayPal özel ödeme işlemleri
print("Processing PayPal payment")
# PayPal security_code yerine email adresi ile doğrulama kabul ediyor.
print(f"Verifying email: {self.email}")
payment_processor = PaymentProcessor()
# Mevcut fonksiyonelite ile kredi kartı ödeme işlemi
credit_card_payment = CreditCardPayment("1234")
payment_processor.process_payment(credit_card_payment)
paypal_payment = PayPalPayment("client@example.com")
payment_processor.process_payment(paypal_payment)
Payment üst sınıfındaki ve alt sınıflarındaki (CreditCardPayment ve PayPalPayment) make_payment yöntemi, beklenen davranışı koruyarak aynı davranışa sahiptir.
PaymentProcessor sınıfının process_payment yöntemi artık herhangi bir ek parametre olmadan bir Payment nesnesini kabul ediyor. Belirli alt sınıf örneğinden bağımsız olarak Payment nesnesinin make_payment yöntemini çağırır. Herhangi bir alt sınıf örneği, beklenen davranışı bozmadan üst sınıf örneğini değiştirebileceğinden, bu LSP'ye uygundur.
Ek olarak, CreditCardPayment ve PayPalPayment alt sınıfları artık ilgili __init__
metodlarında başlatılan kendi özel özniteliklerine(attributes) (sırasıyla security_code ve email) sahiptir. Her alt sınıftaki make_payment yöntemi, ödeme yöntemine özgü ödeme mantığını işler ancak yöntemin davranışını değiştirmez.