里氏替换原则(LSP)描述了,子类可以扩展父类的功能,但是不能改变父类原有的功能
    优点:

    1. 里氏替换时实现开闭原则的重要方式之一
    2. 避免了重写父类造成了可复用性变差的缺点
    3. 类的扩展不会对已有系统引入新的异常,降低代码出错的可能
    4. 加强了程序的健壮性

    实现方式:最直接的应用场景就是子类在继承父类的时候,除了完成扩展功能之外尽量避免重写父类的方法

    反例:枪可以射击和杀人,那么玩具枪呢?

    1. public static void main(String[] args) {
    2. // 手枪射击并杀人
    3. Gun handgun = new HandGun();
    4. handgun.shoot();// 手枪射击
    5. handgun.kill(); // 手枪杀人
    6. // 玩具枪射击并杀人
    7. Gun toyGun = new ToyGun();
    8. toyGun.shoot(); // 玩具枪射击
    9. toyGun.kill(); // java.lang.RuntimeException: 玩具枪不能杀人!
    10. }
    11. // 基类
    12. interface Gun{
    13. // 射击
    14. void shoot();
    15. // 杀人
    16. void kill();
    17. }
    18. // 手枪
    19. static class HandGun implements Gun{
    20. @Override
    21. public void shoot() {
    22. System.out.println("手枪射击");
    23. }
    24. @Override
    25. public void kill() {
    26. System.out.println("手枪杀人");
    27. }
    28. }
    29. // 玩具枪
    30. static class ToyGun implements Gun{
    31. @Override
    32. public void shoot() {
    33. System.out.println("玩具枪射击");
    34. }
    35. @Override
    36. public void kill() {
    37. throw new RuntimeException("玩具枪不能杀人!");
    38. }
    39. }

    正例:针对以上问题,应该再抽象一个只会枪的通用功能的基类【射击】,如下:

    1. public static void main(String[] args) {
    2. // 手枪射击杀人
    3. Gun handGun = new HandGun();
    4. handGun.shoot(); // 手枪射击
    5. handGun.kill(); // 手枪杀人
    6. // 玩具枪射击
    7. AbstractGun toyGun = new ToyGun();
    8. toyGun.shoot(); // 玩具枪射击
    9. }
    10. // 抽象基类,只具备射击功能
    11. interface AbstractGun{
    12. // 射击
    13. void shoot();
    14. }
    15. // 基类,扩展了杀人功能
    16. interface Gun extends AbstractGun{
    17. // 射击
    18. void kill();
    19. }
    20. // 手枪
    21. static class HandGun implements Gun {
    22. @Override
    23. public void shoot() {
    24. System.out.println("手枪射击");
    25. }
    26. @Override
    27. public void kill() {
    28. System.out.println("手枪杀人");
    29. }
    30. }
    31. // 玩具枪
    32. static class ToyGun implements AbstractGun {
    33. @Override
    34. public void shoot() {
    35. System.out.println("玩具枪射击");
    36. }
    37. }