将 Scanner 对象作为构造函数参数传递给 UserInterface class

Passing Scanner object as a constructor parameter to the UserInterface class

当我在观看有关如何将 UserInterface 与程序逻辑分离的 youtube 视频时,视频中的人将扫描器 class 对象作为参数传递给了 UserInterface class 的构造函数从主要方法。像这样:

public class UserInterface {
TodoList list;
Scanner input;

UserInterface(TodoList list,Scanner input){
    this.list=list;
    
    this.input=input;
    
}
}

我的问题是,他为什么不在 UserInterface class 中创建 Scanner class 对象,而是将 Scanner 对象作为参数从 Main class 传递。

因为扫描仪是一种资源。这是一个非常奇怪的资源; 通常 资源用于短暂的资源(例如,想法是在应用程序完全退出之前停止需要该资源),以及整个 class 中的一个(例如, 你可以打开 1 个文件,或者一百万个。'file' 这个概念是多种多样的;你可以有很多文件)。 System.in 很奇怪;你不想关闭它,而且只有一个。

这使它成为一种奇怪的资源。

然而,它是一个,最好将资源视为单一实体。您不想同时创建 2 个单独的文件阅读器。出于同样的原因,您不需要 2 个扫描仪。扫描器可以(并且可以!)缓存,所以如果您在一台扫描器上调用 .hasNextInt() 然后在另一台扫描器上调用 .next(),事情就会变得很奇怪,因为扫描器并非设计用于执行此操作。

让我试着这样说:System.in 是一个全局常量。因此任何消耗 System.in 的扫描器也应该是,因为它被指定为可能缓存东西的东西。

另外,这也打开了允许您的 UserInterface class 对不同输入进行操作的大门。也许有一天,您希望从互联网连接或包含一系列命令的批处理文件中获取输入。或者,更简单的,你想写一个自动化测试。

Scanner 本身并不意味着:“来自标准输入”。你可以用很多东西做一个扫描仪:文件、网络连接、硬编码字符串,任何你想要的东西,真的。