有人能告诉我下面的例子是否违反了LSP吗?
我有一个例子:
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public void validate() {
if (age == null || age < 0) {
throw new IllegalArgumentException("Age can not be null");
}
}
}
和子类:
public class Employee extends Person {
private String employeeCode;
public Employee(String name, Integer age, String employeeCode) {
super(name, age);
this.employeeCode = employeeCode;
}
@Override
public void validate() {
super.validate();
if (employeeCode == null) {
throw new IllegalArgumentException("Employee code can not be null");
}
}
}
和主类:
public class Main {
public static void main(String[] args) {
Person person = new Person("Person", 10);
validate(person); // will be ok. does not throw any exception
Person employee = new Employee("Employee", 30, null);
validate(employee); // will be throw IllegalArgumentException because subtype's employee code is null
}
public static void validate(Person p) {
p.validate();
}
}
在此示例中,子类添加名为 employeeCode
的新属性,并通过对其自己的属性 employeeCode
进行附加检查来覆盖方法验证
。
在main方法中,我创建了2个对象。第一个是Person
类型的对象,第二个是员工
类型的对象。
当验证人员时,因为所有前提条件都是正确的,所以它是正确的,但是对于员工,它将抛出< code > IllegalArgumentException ,因为它与前提条件不匹配
员工
是否由于在员工代码
上添加新的验证而违反LSP?IllegalArgumentExcgon("员工代码不能为空")
更改为另一个异常NullPointerExcsion
。那么它是否因为在子类型中引入了新的异常类型(哪个超级类型没有)而违反了LSP呢?
> < li>
不,当调用< code>validate时,< code>Person和< code>Employee的实例具有完全相同的行为范围。也就是说,调用它要么会导致抛出< code > IllegalArgumentException ,要么不会,因此调用< code>validate并正确处理对< code>Person调用它的结果的任何代码都不会无法正确处理对< code>Employee调用它的结果。
不适用
在我看来:由于IllegalArgumentException
和NullPointerException
都是未经检查的异常,因此它们不构成contract的一部分,该contract有权抛出运行时异常
的任何子类。更好的设计应该是将抛出ValidationException
作为validate
签名的一部分。
正如@jaco0646在上面的评论中所说,Java不允许您正式指定方法的所有内容。
假设我编写了Person
的另一个子类,并决定我的va