简体   繁体   English

ID和EAN继承可能违反Liskov替代原则

[英]ID and EAN inheritance may violate Liskov Substitution Principle

I have a design question for my application. 我对我的应用程序有一个设计问题。

I have a product and a category. 我有一个产品和一个类别。 Both must have an ID. 两者都必须有一个ID。

Category can have any positive integer as an ID. 类别可以具有任何正整数作为ID。 (-> Id-class) (-> ID级)

Product must have an positive integer between 8 & 13 ciphers as an ID. 产品的ID必须为8到13个密码之间的正整数。 (-> Ean-class) (->精益班)

Since that's the only thing these classes do (create an id) and a getter/setter with the correct check. 由于这是这些类唯一的操作(创建ID)和具有正确检查的getter / setter方法。

To reduce code (DRY) I let Ean inherit from Id. 为了减少代码(DRY),我让Ean从ID继承。 But won't that violate Liskov (LSP)? 但是那不会违反Liskov(LSP)吗?

My question: 我的问题:

  1. Is my LSP-reasoning correct? 我的LSP推理正确吗? If yes: 如是:
  2. Should I solve it with creating an interface? 我应该通过创建界面来解决它吗? (seems like duplicate code) Or is there another solution? (好像重复的代码)还是还有其他解决方案?

Thanks in advance! 提前致谢!

Identifier.java Identifier.java

public class Identifier {

    private Long id = 1000000000000L;

    public Identifier(){

    }

    public Identifier(Long id){
        setId(id);
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}

Ean.java Ean.java

public class Ean extends Identifier {

    private final static int MIN_AMOUNT_OF_CIPHERS = 8;

    private final static int MAX_AMOUNT_OF_CIPHERS = 13;

    private final static String ERROR_EAN_LENGTH = "err_ean_length";

    public Ean() {
    }

    public Ean(Long ean) throws DomainException {
        setEan(ean);
    }

    public Long getEan() {
        return getId();
    }

    public void setEan(Long ean) throws DomainException {
        if (String.valueOf(ean).length() < MIN_AMOUNT_OF_CIPHERS
                || String.valueOf(ean).length() > MAX_AMOUNT_OF_CIPHERS) {
            throw new DomainException(ERROR_EAN_LENGTH);
        }
        setId(ean);
}

Is my LSP-reasoning correct? 我的LSP推理正确吗?

Answer: no 答:不可以

It looks like any place an Id is accepted, an Ean instance would be valid, right? 好像在任何地方都可以接受ID,一个Ean实例将是有效的,对吧? That's what LSP is all about. 这就是LSP的全部意义。 That's because Ean is a subset of valid Id's. 这是因为Ean是有效ID的子集。 Any Ean is a valid Id but the opposite isn't always true. 任何Ean都是有效ID,但并非总是如此。

Should I solve it with creating an interface? 我应该通过创建界面来解决它吗? (seems like duplicate code) Or is there another solution? (好像重复的代码)还是还有其他解决方案?

You could have an interface and two specific implementations (Id and Ean). 您可能有一个接口和两个特定的实现(Id和Ean)。 I would probably do that, because for me there's not reason to make Ean subclass Id. 我可能会这样做,因为对我而言,没有理由使Ean成为子类ID。 Both could implement a single interface aimed to serve as a identifier unit. 两者都可以实现旨在用作标识符单元的单个接口。

EDIT: The problem in your inheritance model is that an Ean instance could be inconsistent if you call setId() method inherited from parent class. 编辑:继承模型中的问题是,如果调用从父类继承的setId()方法,则Ean实例可能不一致。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM