对子类实例使用超类类型 [英] Using superclass type for subclass instance

查看:65
本文介绍了对子类实例使用超类类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题已经问了很多,但是我认为通常的答案远远不能令人满意.

I know this question has been asked a lot, but the usual answers are far from satisfying in my view.

具有以下类层次结构:

class SuperClass{}
class SubClass extends SuperClass{}

人们为什么使用这种模式来实例化SubClass:

why does people use this pattern to instantiate SubClass:

SuperClass instance = new SubClass();

代替这个:

SubClass instance = new SubClass();

现在,我看到的常见答案是,这是为了将 instance 作为参数发送给需要SuperClass实例的方法,如下所示:

Now, the usual answer I see is that this is in order to send instance as an argument to a method that requires an instance of SuperClass like here:

void aFunction(SuperClass param){}

//somewhere else in the code...
...
aFunction(instance);
...

但是我可以将SubClass的实例发送给aFunction,而不管持有它的变量的类型如何!意味着以下代码将编译且运行时不会出错(假定先前提供的aFunction定义):

But I can send an instance of SubClass to aFunction regardless of the type of variable that held it! meaning the following code will compile and run with no errors (assuming the previously provided definition of aFunction):

SubClass instance = new SubClass();
aFunction(instance);

实际上,AFAIK变量类型在运行时是没有意义的.它们仅由编译器使用!

In fact, AFAIK variable types are meaningless at runtime. They are used only by the compiler!

将变量定义为SuperClass的另一个可能的原因是,如果它具有多个不同的子类,并且该变量应该在运行时切换到多个子类的引用,但是例如,我只看到了这种情况在类中发生(不是super,不是子类.绝对不足以需要通用模式...

Another possible reason to define a variable as SuperClass would be if it had several different subclasses and the variable is supposed to switch it's reference to several of them at runtime, but I for example only saw this happen in class (not super, not sub. just class). Definitly not sufficient to require a general pattern...

推荐答案

这种类型的编码的主要参数是由于 Liskov替代原则,其中指出,如果 X 是类型为 T 的子类型,则 T 的任何实例都应该能够用 X 换出.

The main argument for this type of coding is because of the Liskov Substituion Principle, which states that if X is a subtype of type T, then any instance of T should be able to be swapped out with X.

这样做的好处很简单.假设我们有一个包含属性文件的程序,如下所示:

The advantage of this is simple. Let's say we've got a program that has a properties file, that looks like this:

mode="Run"

您的程序如下所示:

public void Program
{
    public Mode mode;

    public static void main(String[] args)
    {
        mode = Config.getMode();
        mode.run();
    }
}

因此,简短地说,该程序将使用配置文件来定义该程序将以哪种模式启动.在 Config 类的 getMode()中可能看起来像这样:

So briefly, this program is going to use the config file to define the mode this program is going to boot up in. In the Config class, getMode() might look like this:

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模式,则将无法使用这种功能.

Now, because you have a reference of type Mode, you can completely change the functionality of your program with simply changing the value of the mode property. If you had public RunMode mode, you would not be able to use this type of functionality.

为什么这是一件好事

此模式非常流行,因为它可以打开程序以实现可扩展性.这意味着,如果作者希望实现此类功能,则只需少量更改即可实现此类所需功能.我的意思是,来吧.您只需更改一个配置文件中的一个单词,即可完全更改程序流程,而无需编辑任何一行代码.这是理想的.

This pattern has caught on so well because it opens programs up for extensibility. It means that this type of desirable functionality is possible with the smallest amount of changes, should the author desire to implement this kind of functionality. And I mean, come on. You change one word in a config file and completely alter the program flow, without editing a single line of code. That is desirable.

这篇关于对子类实例使用超类类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆