Prinsip Pergantian Barbara Liskov (Prekondisi dan Pascakondisi)

Mengapa begitu banyak orang bermasalah dengan prinsip ini? Jika kita mengambil bukan "muskil", tetapi definisi yang lebih sederhana, maka bunyinya seperti ini:





Kelas yang mewarisi harus melengkapi, bukan menimpa, perilaku kelas dasar.





Kedengarannya jelas dan cukup logis, kami tidak setuju. tapi bagaimana cara mencapai ini? Untuk beberapa alasan, banyak orang melewatkan informasi tentang prasyarat dan pascakondisi , yang menjelaskan dengan sempurna apa yang perlu dilakukan.





Dalam artikel ini, kami TIDAK akan mempertimbangkan contoh umum dari prinsip ini, yang sudah ada banyak bahan (contoh dengan persegi dan persegi panjang atau kontrol termostat ). Di sini kita akan membahas sedikit lebih detail tentang konsep-konsep seperti "Prasyarat" , "Kondisi setelah" , mempertimbangkan apa itu kovarians, kontravarian dan invarian , serta apa itu "kendala historis" atau "aturan sejarah".





Prasyarat tidak dapat diperkuat dalam subkelas

β–ͺ️ Dengan kata lain, kelas anak tidak boleh membuat lebih banyak prasyarat daripada yang ditentukan di kelas dasar untuk melakukan beberapa perilaku bisnis. Berikut contohnya:





<?php

class Customer
{
    protected float $account = 0;

    public function putMoneyIntoAccount(int|float $sum): void
    {
        if ($sum < 1) {
            throw new Exception('       1$');
        }

        $this->account += $sum;
    }
}

class  MicroCustomer extends Customer
{
    public function putMoneyIntoAccount(int|float $sum): void
    {
        if ($sum < 1) {
            throw new Exception('       1$');
        }

        //  
        if ($sum > 100) { 
            throw new Exception('      100$');
        }

        $this->account += $sum;
    }
}
      
      



​ . !





«», , .





, , .





, , Bar->process()



, .





<?php

class Foo
{
    public function process(int|float $value)
    {
       // some code
    }
}

class Bar extends Foo
{
    public function process(int|float|string $value)
    {
        // some code
    }
}
      
      



, VIPCustomer



putMoneyIntoAccount



( ) Money



, ( Dollars



).





<?php

class Money {}
class Dollars extends Money {}

class Customer
{
    protected Money $account;

    public function putMoneyIntoAccount(Dollars $sum): void
    {
        $this->account = $sum;
    }
}

class VIPCustomer extends Customer
{
    public function putMoneyIntoAccount(Money $sum): void
    {
        $this->account = $sum;
    }
}
      
      



, , .





​️ , . .





<?php

class Customer
{
    protected Dollars $account;

    public function chargeMoney(Dollars $sum): float
    {
        $result = $this->account - $sum->getAmount();

        if ($result < 0) { // 
            throw new Exception();
        }

        return $result;
    }
}

class  VIPCustomer extends Customer
{
    public function chargeMoney(Dollars $sum): float
    {
        $result = $this->account - $sum->getAmount();

        if ($sum < 1000) { //   
            $result -= 5;  
        }
       
        //    
      
        return $result;
    }
}
      
      



​ , . !





- «», (?!), .





. render()



, JpgImage



, Image



, Renderer



.





<?php

class Image {}
class JpgImage extends Image {}

class Renderer
{
    public function render(): Image
    {
    }
}

class PhotoRenderer extends Renderer
{
    public function render(): JpgImage
    {
    }
}
      
      



​️ . . :)





.





- .





β€” , . , .





.





<?php 

class Wallet
{
    protected float $amount;
    //        
}
      
      



(Β« Β»):





.





, . , . 





<?php

class Deposit
{
    protected float $account = 0;

    public function __construct(float $sum)
    {
        if ($sum < 0) {
            throw new Exception('      ');
        }

        $this->account += $sum;
    }
}

class VipDeposit extends Deposit
{
    public function getMoney(float $sum)
    {
        $this->account -= $sum;
    }
}
      
      



​ Deposit



. VipDeposit



, account



, Deposit



. .





.





, , , , .





Perlu disebutkan untuk berusaha menyingkirkan kondisi pra / pasca. Idealnya, mereka harus didefinisikan sebagai parameter input / output dari metode (misalnya, dengan meneruskan objek nilai siap pakai ke tanda tangan dan mengembalikan objek valid tertentu ke output).





Semoga bermanfaat.





Sumber dari

  1. Wiki - Prinsip Pergantian Barbara Liskov





  2. Metanit





  3. PHP.watch





  4. Saluran Telegram, dengan catatan singkat








All Articles