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

Java ID和EAN继承可能违反Liskov替换原则,java,oop,inheritance,design-patterns,liskov-substitution-principle,Java,Oop,Inheritance,Design Patterns,Liskov Substitution Principle,我对我的申请有一个设计问题 我有一个产品和一个类别。两者都必须有一个ID 类别可以有任何正整数作为ID。->ID类 产品的ID必须为8到13个密码之间的正整数。->Ean类 因为这是这些类所做的唯一一件事,它们使用正确的检查来创建id和getter/setter 为了减少代码干涸,我让Ean从Id继承。但这不会违反Liskov LSP吗 我的问题: 我的LSP推理正确吗? 如果是: 我应该通过创建一个接口来解决这个问题吗?看起来像是重复的代码,或者有其他解决方案吗? 提前谢谢 Identifie

我对我的申请有一个设计问题

我有一个产品和一个类别。两者都必须有一个ID

类别可以有任何正整数作为ID。->ID类

产品的ID必须为8到13个密码之间的正整数。->Ean类

因为这是这些类所做的唯一一件事,它们使用正确的检查来创建id和getter/setter

为了减少代码干涸,我让Ean从Id继承。但这不会违反Liskov LSP吗

我的问题:

我的LSP推理正确吗? 如果是: 我应该通过创建一个接口来解决这个问题吗?看起来像是重复的代码,或者有其他解决方案吗? 提前谢谢

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;
    }

}
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);
}
我的LSP推理正确吗

回答:没有

看起来任何接受Id的地方,Ean实例都是有效的,对吗?这就是LSP的意义所在。这是因为Ean是有效Id的子集。任何Ean都是有效的Id,但相反的情况并不总是正确的

我应该通过创建一个接口来解决这个问题吗?看起来像是复制品 代码还是有其他解决方案

您可以有一个接口和两个特定的实现Id和Ean。我可能会这样做,因为对我来说,没有理由创建Ean子类Id。两者都可以实现一个接口,作为标识符单元

编辑:
继承模型中的问题是,如果调用从父类继承的setId方法,Ean实例可能不一致

setEan和getEan不应该存在。您应该替代setId。否则,任何人都可以在Ean上调用setId12L,从而在其中存储无效值。您也不应该从构造函数调用可重写的方法。标识符应该是不可变的IMHO。好了,现在setEan和getEan是get/setId。所以您应该创建一个单独的方法来检查EAN?否则,您将拥有两倍的签入构造函数和setter?这不是LSP问题的答案,但EAN实际上不应该被建模为数字。它是一个具有长度和校验和限制的数字字符串。