Warum haben so viele Probleme mit diesem Prinzip? Wenn wir nicht "abstrus", sondern eine einfachere Definition nehmen, dann klingt das so:
Die erbende Klasse sollte das Verhalten der Basisklasse ergänzen und nicht überschreiben.
Es klingt klar und ziemlich logisch, wir sind nicht einverstanden. aber verdammt wie kann man das erreichen? Aus irgendeinem Grund überspringen viele Leute einfach Informationen über Vor- und Nachbedingungen , die nur perfekt erklären, was zu tun ist.
In diesem Artikel werden KEINE allgemeinen Beispiele für dieses Prinzip betrachtet, für die es bereits viele Materialien gibt (Beispiel mit einer quadratischen und einer rechteckigen oder Thermostatsteuerung ). Hier werden wir uns etwas eingehender mit Konzepten wie "Voraussetzungen" , "Nachbedingungen" befassen , überlegen, was Kovarianz, Kontravarianz und Invarianz sind und was "historische Zwänge" oder "Regeln der Geschichte" sind.
Voraussetzungen können in einer Unterklasse nicht gestärkt werden
️ Mit anderen Worten, untergeordnete Klassen sollten nicht mehr Voraussetzungen schaffen als in der Basisklasse definiert, um ein gewisses Geschäftsverhalten zu erzielen. Hier ist ein Beispiel:
<?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
. .
.
, , , , .
Es ist erwähnenswert, sich zu bemühen, die Vor- / Nachbedingungen loszuwerden. Idealerweise sollten sie als Eingabe- / Ausgabeparameter der Methode definiert werden (z. B. indem vorgefertigte Wertobjekte an die Signatur übergeben und ein bestimmtes gültiges Objekt an die Ausgabe zurückgegeben werden).
Hoffe es war hilfreich.