Maison >Java >javaDidacticiel >Principe de substitution de Liskov

Principe de substitution de Liskov

PHPz
PHPzoriginal
2024-08-25 22:30:361130parcourir

Liskov Substitution Principle

Les objets doivent être remplaçables par leur sous-type sans affecter l'exactitude du code

Comprenons cela avec l'héritage (Est-une relation)
exemple : l'autruche est un oiseau, le bossu est une voiture, etc.

Exemple : La voiture de course est une voiture

public class Car{
    public double getCabinWidth(){
        //return cabin width
    }
}
public class RacingCar extends Car{
    @Override
    public double getCabinWidth(){
        //UNIMPLEMENTED
    }
    public double getCockpitWidth(){
        //return the cockpit width of the racing car
    }
}

RacingCar remplace le getCabinWidth() de la classe de voiture mais le laisse non implémenté car les voitures de course n'ont pas de largeur de cabine (si vous voyez une voiture de course de Formule 1, elle n'a pas d'espace intérieur, tout ce qu'il a, c'est juste un cockpit où est assis le conducteur)
C'est pourquoi l'espace intérieur d'une voiture de course est appelé cockpit.
Remarque : les voitures de course ont certaines spécifications qui peuvent ne pas correspondre à la voiture générique

public class CarUtil{
    Car car1 = new Car();
    Car car2 = new Car();
    Car car3 = new RacingCar();

    List<Car> myCars = new ArrayList<>();
    myCars.add(car1);
    myCars.add(car2);
    myCars.add(car3);
    // this will not work in 3rd iteration, because the getCabinWidth() in RacingCar is not implemented 
    for(Car car  : myCars){
        System.out.println(car.getCabinWidth());
    }
}

Il s'agit d'une conception qui a été exposée, car la boucle for échouera pour la troisième itération.
Pour résoudre ce problème, nous devons frapper à la racine qui est l'héritage lui-même.


Solution 1 : (Briser la Hiérarchie)

Nous devons rompre l'héritage, à la place, nous trouverons un parent commun pour Car et RacingCar

Nous allons créer une classe parent très générique appelée Vehicle

public class Vehicle{
    public double getInteriorWidth(){
        //return the interior width
    }
}
public class Car extends Vehicle{
    @Override
    public double getInteriorWidth(){
        return this.getCabinWidth();
    }
    public double getCabinWidth(){
        //return cabin width
    }
}
public class RacingCar extends Vehicle{
    @Override
    public double getInteriorWidth(){
        return this.getCockpitWidth();
    }

    public double getCockpitWidth(){
        //return the cockpit width of the racing car
    }
}
public class VehicleUtils{
    Vehicle vehicle1 = new Car();
    Vehicle vehicle2 = new Car();
    Vehicle vehicle2 = new RacingCar();

    List<Vehicle> vehicles = new ArrayList<>();
    vehicles.add(vehicle1);
    vehicles.add(vehicle2);
    vehicles.add(vehicle3);
    for(Vehicle vehicle : vehicles){
        System.out.println(vehicle.getInteriorWidth());
    } 
}

**Briser la hiérarchie : Briser la hiérarchie si la substitution échoue


Solution 2 : Dites, ne demandez pas

Prenons un autre exemple d'Amazon
Amazon offre un montant x de remise sur tous les produits tiers.
Et offre 1,5 fois x sur tous ses produits maison (les produits Amazon Basics sont des produits maison Amazon)

public class Product{
    public double discount = 20;//x amount of discount on all the third-party products on Amazon
    public double getDiscount(){
        return discount;
    }
}
public class InHouseProduct extends Product{
    public void applyDiscount(){
        discount  = discount*1.5;// 1.5 times more discount on InHouseProducts
    }
}
public class PricingUtils{
    Product p1 = new Product();
    Product p2 = new Product();
    Product p2 = new InHouseProduct();
    List<Product> products = new ArrayList<>();
    products.add(p1);
    products.add(p2);
    products.add(p2);
    for(Product product : products){
        if(product instanceOf InHouseProduct){
            ((InHouseProduct)product).applyDiscount();
        }
        System.out.println(product.getDiscount());
    }
}

Notez que l'instruction if est impliquée dans la mise à jour du montant de la remise d'InHouseProduct ce qui est contre le principe de substitution de Liskov (car nous aurions dû pouvoir remplacer l'objet Product par son sous-type InHouseProduct), mais ici dans la déclaration if, nous mettons à jour manuellement le montant de la remise, ce qui ne devrait pas être fait.

Une légère modification dans la classe InHouseProduct résoudra ce problème

public class InHouseProduct extends Product{

    @Override
    public double getDiscount(){
        applyDiscount();
        return discount;
    }
    public void applyDiscount(){
        discount  = discount*1.5;
    }
}

Et enfin, supprimer l'instruction if de la classe PricingUtils

public class PricingUtils{
    Product p1 = new Product();
    Product p2 = new Product();
    Product p2 = new InHouseProduct();
    List<Product> products = new ArrayList<>();
    products.add(p1);
    products.add(p2);
    products.add(p2);
    for(Product product : products){
        System.out.println(product.getDiscount());
    }
}

Dites, ne demandez pas : Ici, nous disons à la classe utils d'imprimer toutes les réductions et la classe utils n'a rien à demander (comme elle demandait si déclaration plus tôt)


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn