当你有一个基类和扩展这个基类的2个类时,如何建模域,并且只有一个派生类与另一个对象有关系。
示例:
public abstract class Base
{
public abstract void method();
}
public class1 extends Base
{
public void method()
{
do some stuff
}
}
public class2 extends Base
{
private Class3 class3;
public void method()
{
do other stuff
}
public Class3 getClass3(){...}
public void setClass3(Class3 class3){...}
}
这种模式打破Liskov原则吗?我认为是因为与class3的这种关系,所以我们必须弄清楚如何在没有这种关系的情况下建模或将这种关系移到Base。如果我有一个处理Class2的程序的一部分来处理Class3的关系,我就不能使用基类而不转换为class2。
这是正确的吗?
...澄清
让我们在学习模型中思考。我们有课程和课程。我们还可以提供在线课程和特殊课程。在本科课程中,我们可能会面临此培训的费用。因此,成本只对主流环境有意义。 CourseClasses可以有范围日期或定量日期。
今天我有这个模特:
Course
{
...
}
public abstract class CourseClass
{
private Course course;
// getter and setter to course
public abstract Enrollment enroll(Person student);
}
public class QuantitativeCourseClass
{
public Enrollment enroll(Person student)
{
// enroll for quantitative
}
}
public class RangeCourseClass
{
public Enrollment enroll(Person student)
{
// enroll for range
}
}
现在我必须处理费用,直到这一刻,特殊课程对我来说并不重要,但现在,成本只对主流环境有意义。
我的问题是:我需要在成本模块中处理CourseClass对象,因为我需要一些courseClass,但成本的关系是RangeCourseClass,因为QuantitativeCourseClass对于prensecial环境没有意义。
关于liskov的问题是关于如何让我的团队在这个模型中进行一些修改。
答案 0 :(得分:1)
如果class3与base无关,那么它不应该在base中。你不能“破坏”LSP,因为编译器强制执行它。向下转换不是首选,但这样做不会破坏LSP。
继承的目的是建立“is-a”关系。猫是一种(n)动物。丰田是一辆汽车。
你所说的是将丰田会徽搬到汽车类只是因为你想让事情变得更容易。这根本不是好设计。
简而言之,将事物移动到基类的设计要比转向特定类的设计更差。
答案 1 :(得分:0)
我认为你已经混淆了LSP(Liskov Substitution Principle)的方向:LSP是(强)行为子类型,而不是强大的行为超类型。因此LSP不会对您的示例起作用,但对于您的示例:
这种模式打破Liskov原则吗?我想是因为这个 与class3的关系,所以我们必须弄清楚如何建模 这种关系或将此关系移至Base。如果我有一部分 处理Class2以处理与Class3 I的关系的程序 如果没有强制转换为class2,则无法使用基类。
你的模型没有打破LSP。如果你有一部分程序使用一些专门处理Class2的变量var(即Base中没有的部分),你需要声明var为Class2 。所以不需要垂头丧气。并且LSP保证var也表现为Base,因此也不需要显式的upcast。
答案 2 :(得分:0)
据我了解,如果不了解问题方面(例如几何),就无法查看问题。所以,我无法理解你的架构的含义。例如,着名的LSP违规示例: 正方形:矩形 - 当它站在" side"时看起来很好。但是,当你开始使用并且放置一些函数时,你可以看到问题。