Skip to content

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.