我知道这个问题已经被问了很多,但我认为通常的答案远不能令人满意。
给定以下类层次结构:
class SuperClass{}
class SubClass extends SuperClass{}
为什么人们使用这种模式来实例化子类:
SuperClass instance = new SubClass();
而不是这个:
SubClass instance = new SubClass();
现在,我看到的通常答案是,这是为了将 instance
作为参数发送给需要 SuperClass 实例的方法,如下所示:
void aFunction(SuperClass param){}
//somewhere else in the code...
...
aFunction(instance);
...
但我可以将 SubClass 的实例发送到 aFunction,而不管保存它的变量类型如何!这意味着以下代码将编译并运行而不会出现错误(假设先前提供了 aFunction 的定义):
SubClass instance = new SubClass();
aFunction(instance);
事实上,AFAIK 变量类型在运行时是没有意义的。它们仅供编译器使用!
将变量定义为 SuperClass 的另一个可能原因是,如果它有几个不同的子类并且该变量应该在运行时切换它对其中几个子类的引用,但例如我只看到这种情况发生在类中(不是 super,不是子。只是类)。绝对不足以要求通用模式...
最佳答案
这种编码的主要论点是因为 Liskov Substituion Principle ,它指出如果 X
是类型 T
的子类型,那么 T
的任何实例都应该能够与 交换X
。
这样做的好处很简单。假设我们有一个具有属性文件的程序,如下所示:
mode="Run"
你的程序看起来像这样:
public void Program
{
public Mode mode;
public static void main(String[] args)
{
mode = Config.getMode();
mode.run();
}
}
简单地说,这个程序将使用配置文件来定义这个程序将要启动的模式。在 Config
类中,getMode()
可能看起来像这样:
public Mode getMode()
{
String type = getProperty("mode"); // Now equals "Run" in our example.
switch(type)
{
case "Run": return new RunMode();
case "Halt": return new HaltMode();
}
}
为什么否则这行不通
现在,因为您有一个类型为 Mode
的引用,您只需更改 mode
属性的值就可以完全改变程序的功能。如果您有 public RunMode 模式
,您将无法使用此类功能。
为什么这是一件好事
这种模式之所以流行,是因为它为程序的可扩展性打开了大门。这意味着如果作者希望实现此类功能,则只需进行最少的更改就可以实现此类理想的功能。我的意思是,来吧。您更改配置文件中的一个词并完全改变程序流程,而无需编辑一行代码。这是可取的。
关于java - 对子类实例使用父类(super class)类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19113285/