Câu trả lời là "bởi vì một máy quét có trạng thái."
Nhìn vào mã cho java.util.Scanner , bạn sẽ thấy một số trường riêng như bộ đệm và thông tin liên quan của nó, Trình so khớp, Mẫu, nguồn đầu vào, thông tin về việc nguồn có bị đóng hay không, loại về điều cuối cùng được khớp, thông tin về việc liệu cuối cùng có khớp hợp lệ hay không, cơ số được sử dụng cho các số, miền địa phương (thông tin về việc bạn đang sử dụng .
hoặc ,
như một dấu tách hàng nghìn) và bộ đệm LRU của chính nó cho các mẫu được sử dụng gần đây , thông tin về ngoại lệ cuối cùng gặp phải, một số thông tin về phân tích số, một số thông tin về phân tích cú pháp booleans, thêm một chút thông tin về phân tích số nguyên ... và tôi nghĩ đó là về nó.
Như bạn có thể thấy, đó là một khối văn bản khá lớn ở đó. Đó là trạng thái của Máy quét. Để biến Máy quét thành một lớp tĩnh, trạng thái đó sẽ cần được lưu trữ ở một nơi khác. Cách làm C thực sự không có nhiều trạng thái với nó. Bạn đã có một fscanf
. FILE duy trì một số trạng thái về vị trí của nó (nhưng cần phải được thông qua cho mỗi lần gọi fscanf
). Nếu có lỗi, bạn phải xử lý nó (và sau đó bạn bắt đầu viết mã trông như thế này ) - và điều đó không cho bạn biết thông tin như "Tôi đang mong đợi một Integer, nhưng đã tìm thấy String."
Khi một người nhìn vào Máy quét tĩnh về mặt lý thuyết - tất cả trạng thái được duy trì bên ngoài lớp, nó không được gói gọn trong lớp. Các bit khác của mã có thể tinker với các biến đó. Khi các mã khác có thể sửa đổi trạng thái của lớp, sẽ rất khó để suy luận về những gì lớp sẽ làm trong bất kỳ tình huống nào.
Bạn có thể, có thể, viết một cái gì đó giống như ScannerState { Locale loc; ... }
và có mã dẫn đến:
ScannerState state = new ScannerState(a whole lot of arguments);
int foo = Scanner.nextInt(state);
Nhưng sau đó, điều này cồng kềnh hơn nhiều so với việc đóng gói trạng thái trong một đối tượng Máy quét ở vị trí đầu tiên (và không cần phải vượt qua trong trạng thái).
Cuối cùng, Máy quét thực hiện giao diện Iterator<String>
có nghĩa là người ta có thể sử dụng nó trong mã như:
Scanner in = new Scanner(someFile);
whie(in.hasNext()) { ... }
Không thể có được một thể hiện của lớp Scanner, kiểu cấu trúc này trở nên cồng kềnh hơn trong một ngôn ngữ hướng đối tượng.