我使用Scanner class来阅读多个类似的文件。我想扩展它以确保它们都使用相同的分隔符,我还可以添加所有对它们都有效的 skipUntilYouFind(String thisHere)等方法。
我可以创建一个包含它们的实用程序类,或者将Scanner类作为变量嵌入到另一个类中,但这更麻烦。
我发现some reasons宣布了一个班级决赛,但为什么要在这里完成?
答案 0 :(得分:4)
可能是因为扩展它并覆盖它的某些方法可能会破坏它。并且更容易覆盖方法会暴露大部分内部工作,所以如果将来他们决定改变那些(出于性能或其他原因),他们将更难以在不破坏所有类的情况下更改类扩展它。
例如,请考虑类中的以下方法:
public boolean nextBoolean() {
clearCaches();
return Boolean.parseBoolean(next(boolPattern()));
}
假设你要覆盖这个,因为你想让'awesome'评估为'true'布尔值(无论出于何种原因)。如果覆盖它,则无法调用super.nextBoolean(),因为这将使用默认逻辑消耗下一个标记。但是如果不调用super.nextBoolean(),则不会调用clearCaches(),可能会破坏其他未覆盖的方法。你不能调用clearCaches(),因为它是私有的。如果他们让它受到保护,但后来意识到它导致性能问题,并且想要一个不再清除缓存的新实现,那么它们可能会破坏你仍然会调用它的覆盖实现。
所以基本上它是这样的,它们可以很容易地改变类中隐藏的部分,这些部分非常复杂,并且可以防止你创建一个破坏的子类(或者一个容易被破坏的类)。
答案 1 :(得分:1)
我想这是出于安全原因。这个类读取用户输入,以便有意图的人可以扩展它,修改它的行为,你就会被搞砸。如果它是最终的,对坏人来说并不容易,因为如果他制作了自己的Scanner类型(而不是java.util.Scanner),那么多态性的原理就会被打破。看到坏人可以聪明地编写一个机器人/脚本,它可以在远程服务器上自动执行此操作......他甚至可以通过编译应用程序中的动态类加载来实现。
答案 2 :(得分:0)
我认为您提供的链接可以解释所有内容。
在你的情况下,似乎你应该更喜欢组合而不是继承。您正在创建一个具有某些预定义行为的实用程序,它可以隐藏Scanner类的部分(或全部)详细信息。
我见过许多使用继承来改变行为的实现。最终结果通常是整体设计,在某些情况下,合同破裂,和/或行为破裂。