申请我们在 运行 之前就知道类型的 类 是一种浪费吗?

Is Polymorphism a waste to apply for the classes that we exactly know the type prior run-time?

运行-time Polymorphism 可以用来让 运行-time 动态加载抽象的确切具体 class class/interface。 (你可以拿 Animal/Dog、Vehicle/Car 个例子)

但是当我们知道确切的具体情况时class@coding-time(编译时),真的需要强行应用多态吗?

But when we know the exact concrete class @coding-time (compile-time), does it really need to forcefully apply polymorphism?

考虑到类型擦除技术,在编译时知道类型不一定是 yes/no 跨越应用程序中的所有代码和对象的整个生命周期的事情。但是,忽略多态性的那些经典用法,还有其他潜在的原因,例如...

  • (抱歉 - 这个很明显)以便在以后另一个可用时更容易更改实现

  • 使 "mock" 测试实现更容易(即提供假装提供某些服务或功能的对象,但具有更多 scripted/controllable/observable 行为让测试进行一些依赖代码)

  • 隐藏可能必须公开的实现方面(例如,在 C++ 中,class/struct 定义必须声明所有受保护和私有成员)

    • 这有时是为了保护知识 属性;在其他时候,可以对实现进行更多更改,而不必更改 "header" 通常会触发重新编译大量相关代码的文件
  • 帮助建模和应用程序设计,使用 "interfaces" 明确指定预期的 API,然后可以在实现充实时提供更稳定的比较参考

当我编写 OO 代码时,我倾向于在赋值的左侧使用最通用的类​​型。这立即意味着我对你的问题的回答是——不。

示例如下:

Animal x = new Dog();
...
x.move();

我这样做的原因是我可能会将操作的开始和结束分成两个不同的操作。我的方法在实践中非常简短。

应用于同一个例子:

function moveDog() {
    move(new Dog());
}

function move(Animal animal) {
    animal.move();
}

如您所见,移动函数知道它真正移动的是哪种动物是没有意义的。

通常,编译器有责任确定在给定的代码库中是否使用重写的 move() 方法进行了任何具体调用。一些编译器可以检测到没有覆盖的方法会受制于它们,然后它们会在编译时删除动态调度。运气好的话,无论 move 函数接收 Animal 还是 Dog,我上面的代码都会编译相同的结果。

现在,这是理论。在实践中,有两件重要的事情。首先,广泛使用的编译器还没有开始使用像检测静态方法调用这样积极的优化技术,而不是需要动态分派的调用。其次,第一件事与我们今天拥有的 CPU 权力无关紧要。

十五年来,我一直在编写高度优化的代码,并且遇到过我不得不考虑多态调用的情况。这就是为什么我强烈建议尽可能多地应用多态性。当需要添加一些 类 以合并新功能时,多态调用可能会成为将新 类 无缝添加到现有设计的工具。如果您在开发过程中使用了过于具体的类型,很容易发生无法向给定代码库添加新功能的情况。