Làm thế nào để '20 giây 'hoạt động trong Scala?


130

Làm thế nào để biên dịch sau đây:

import scala.concurrent.duration._

val time = 20 seconds

Điều gì đang thực sự xảy ra ở đây?

Câu trả lời:


171

Có một vài điều đang diễn ra.

Đầu tiên, Scala cho phép các dấu chấm và dấu chấm được bỏ qua trong nhiều lệnh gọi phương thức, do đó 20 secondstương đương với 20.seconds()*.

Thứ hai, một "chuyển đổi ngầm" được áp dụng. Vì 20là một IntIntkhông có secondsphương thức, trình biên dịch tìm kiếm một chuyển đổi ngầm nhận Intvà trả về một cái gì đó một secondsphương thức, với tìm kiếm bị giới hạn bởi phạm vi của lệnh gọi phương thức của bạn.

Bạn đã nhập WeatherInt vào phạm vi của bạn. Vì DurationIntlà một lớp ẩn với một Inttham số, hàm tạo của nó định nghĩa một Int => DurationIntchuyển đổi ngầm định . DurationIntcó một secondsphương pháp, vì vậy nó thỏa mãn tất cả các tiêu chí tìm kiếm. Do đó, trình biên dịch viết lại cuộc gọi của bạn là new DurationInt(20).seconds**.

* Ý tôi là điều này lỏng lẻo. 20.seconds()thực sự không hợp lệ vì secondsphương thức không có danh sách tham số và do đó, các parens phải được bỏ qua trong lệnh gọi phương thức.

** Trên thực tế, điều này không hoàn toàn đúng vì DurationIntlà một lớp giá trị, vì vậy trình biên dịch sẽ tránh gói số nguyên nếu có thể.


83
Bất kỳ công nghệ đủ tiên tiến là không thể phân biệt với ma thuật.
ripper234

4
May mắn thay, hầu hết các IDE đều có khả năng phân biệt nó! Chuyển đổi ngầm định được sử dụng khá nhiều trong Scala. Nếu bạn chỉ đọc tệp văn bản, nó có thể gây nhầm lẫn ("phương pháp đó đến từ đâu") nhưng với sự hỗ trợ công cụ phù hợp, bạn sẽ có thể tìm đường, lúc đó Scala có thể có ý nghĩa đẹp và súc tích. (ví dụ: 20 giây là dễ đọc hơn nhiều so với new DurationInt(20).seconds()khi bạn biết nó hoạt động như thế nào)
William Billingsley

1
Nếu bạn thấy mình sử dụng những ẩn ý, ​​hãy luôn tự hỏi liệu có cách nào để đạt được điều tương tự mà không cần sự giúp đỡ của họ không. twitter.github.com/effectivescala/#Types và Generics-Implicits
oluies

4
Trên thực tế secondsphương thức được định nghĩa mà không có parens, vì vậy gọi nó bằng parens là một lỗi.
Frank S. Thomas

1
@Frank Đó là một điểm tốt. Tôi không có ý đề nghị bạn có thể viết 20.seconds()bằng Scala, chỉ có điều là trình biên dịch đang dịch cuộc gọi theo cách đó. Thật đáng để chỉ ra rằng Scala yêu cầu bạn bỏ qua parens nếu phương thức tương ứng không có danh sách tham số, như trong trường hợp này.
Aaron Novstrup

7

"Phép thuật" đang diễn ra ở đó được gọi là "chuyển đổi ngầm". Bạn đang nhập các chuyển đổi ngầm định và một số trong số chúng xử lý chuyển đổi giữa Int (và Double) thành Thời lượng. Đó là những gì bạn đang đối phó.


1
Bất cứ ý tưởng tại sao nhập khẩu import scala.concurrent.duration._giải quyết 20 secondsnhưng thực sự nhập DurationConversionsTrait không? EDIT : Chỉ cần nhận ra những gì họ thực sự nhập khẩu DurationInt. Tôi đoán điều này là do bạn không thể nhập Trait thực tế? Chỉ thực hiện cụ thể của Đặc điểm?
franklin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.