3

由于(Liskov)替换原则,以下内容确实有效,该原则表示,如果某个类的实例需要引用,那么您可以替换对该类的任何子类的实例的引用。

public static void main( String[] args ) {
Cat felix = new Cat( );
Object copyCat = felix;
}

现在,据我了解,在这种情况下,我正在创建一个Cat对象(因此正在堆中创建内存空间),然后我将一个名为“felix”的对象引用变量分配给新创建的Cat对象。引用变量的类型是Cat,因此只能控制Cat及其任何子类Cat

然后我创建一个Objecttype 的引用变量Object,并将其指向 felix ( Cat) 对象,该对象可以工作但功能有限,因为 JVM 现在看到 felix 对象的 type Object,因此,例如,如果purr()Cat类,felix 将无法再使用它。

所以 typeCat应该有一个引用,但是我们为 cat 类型的超类(而不是上面定义中所说的子类)提供了一个引用,这是允许的,但功能有限(除非你进行强制转换)。

我是正确的还是错误的?

4

3 回答 3

2

您所做的与 Liskov 替换原则几乎没有关系。

这个原则是判断继承是好主意还是使用继承是错误的规则。显然,每个对象都继承自 "Object" :从 Object 继承永远不会出错。

这是 LSP 适用的示例:

如果你有 :

abstract class Shape {
  abstract public area();
}

class Shape1 extends Shape {
  private width;
  (...)
}

class Shape2 extends Shape {
  private width;
  private length;
  (...)
}

认为 Shape2 继承了 Shape1(将“宽度”属性作为通用属性)是错误的,因为 Shape1 和 Shape2 的 area() 方法会有所不同。

于 2011-04-19T12:13:25.307 回答
1

在我看来,您是根据引用而不是对象来考虑的,这就是为什么您要颠倒规则的定义。

引用维基百科版本的原理:

如果 S 是 T 的子类型,则 T 类型的对象可以替换为 S 类型的对象

(这似乎与您提供的定义相同,我认为它来自您的导师)

在您的示例中, T 是Object, S 是Cat。当您有 T 类型的参考时

Object copyCat;

替换原则的意思是,这个引用可以指向一个类型为 T 的对象或任何类型为 T 的子类的 S 类型的对象。所以以下任何一个都是有效的:

copyCat = new Object();
copyCat = new Cat();

(并且由于我们在Object这里使用它,根据定义,它是任何 Java 类的超类,所以copyCat引用可以指向任何类型的对象。)

我认为这里很重要的一点是,引用的类型决定了可以调用哪些方法,而不管实际对象指向的方法支持哪些方法。这就是为什么可以将任何子类的实例分配给引用的原因。

于 2011-04-19T12:19:44.017 回答
0

它说的是 Cat 类是 Object 类的有效替代品。因此,任何时候某个方法需要 Object 类型的对象时,您都可以替换为 Cat 类型的对象。

于 2011-04-19T12:18:36.927 回答