Các Chapter 2. Type Less, Do More của cuốn sách Programming Scala đề cập:
Khi Loại chú thích rõ ràng được yêu cầu.
Trên thực tế, bạn phải cung cấp chú thích kiểu tường minh trong các trường hợp sau đây:
giá trị Phương pháp trở lại trong các trường hợp sau:
- Khi bạn một cách rõ ràng gọi trở lại trong một phương pháp (ngay cả ở kết thúc).
- Khi phương pháp đệ quy.
- Khi phương thức bị quá tải và một trong các phương pháp gọi một phương thức khác. Phương thức gọi cần chú thích kiểu trả về.
- Khi loại trả về phỏng đoán sẽ tổng quát hơn bạn dự định, ví dụ:
Any
.
Ví dụ:
// code-examples/TypeLessDoMore/method-nested-return-script.scala
// ERROR: Won't compile until you put a String return type on upCase.
def upCase(s: String) = {
if (s.length == 0)
return s // ERROR - forces return type of upCase to be declared.
else
s.toUpperCase()
}
phương pháp quá tải đôi khi có thể đòi hỏi một kiểu trả về rõ ràng. Khi một phương thức như vậy gọi một phương thức khác, chúng ta phải thêm kiểu trả về cho một phương thức thực hiện cuộc gọi, như trong ví dụ này.
// code-examples/TypeLessDoMore/method-overloaded-return-script.scala
// Version 1 of "StringUtil" (with a compilation error).
// ERROR: Won't compile: needs a String return type on the second "joiner".
object StringUtil {
def joiner(strings: List[String], separator: String): String =
strings.mkString(separator)
def joiner(strings: List[String]) = joiner(strings, " ") // ERROR
}
import StringUtil._ // Import the joiner methods.
println(joiner(List("Programming", "Scala")))
Hai joiner
phương pháp nối một List
các chuỗi lại với nhau.
Phương pháp đầu tiên cũng lấy một đối số cho chuỗi dấu phân tách.
Phương pháp thứ hai gọi phương thức đầu tiên với dấu phân cách “mặc định” của một dấu cách.
Nếu bạn chạy tập lệnh này, bạn sẽ gặp phải lỗi sau.
... 9: error: overloaded method joiner needs result type
def joiner(strings: List[String]) = joiner(strings, "")
Kể từ thứ hai phương pháp joiner
gọi đầu tiên, nó đòi hỏi một kiểu tường minh String
trở lại.Nó sẽ giống như thế này:
def joiner(strings: List[String]): String = joiner(strings, " ")
Về cơ bản, xác định kiểu trả về có thể là một thực hành tốt mặc dù Scala có thể suy ra nó.
Randall Schulz nhận xét:
Như một vấn đề của phong cách (cá nhân tôi), tôi cung cấp cho các loại lợi nhuận rõ ràng cho tất cả nhưng những phương pháp đơn giản nhất (về cơ bản, một lớp lót với không có logic có điều kiện).
Hãy nhớ rằng nếu bạn để trình biên dịch suy ra loại kết quả của phương thức, nó có thể cụ thể hơn bạn muốn. (Ví dụ: HashMap thay vì bản đồ.)
Và kể từ khi bạn có thể muốn để lộ giao diện tối thiểu trong kiểu trả về của bạn (xem ví dụ SO question này), loại suy luận có thể nhận được trong cách.
Và về kịch bản cuối cùng ("Khi kiểu trả về suy ra sẽ là tổng quát hơn hơn bạn dự định"), Ken Bloom cho biết thêm:
xác định kiểu trả về khi bạn muốn trình biên dịch để xác minh mã trong hàm trả về loại bạn mong đợi
(Mã lỗi kích hoạt "loại trả về chung hơn mong đợi là:
// code-examples/TypeLessDoMore/method-broad-inference-return-script.scala
// ERROR: Won't compile. Method actually returns List[Any], which is too "broad".
def makeList(strings: String*) = {
if (strings.length == 0)
List(0) // #1
else
strings.toList
}
val list: List[String] = makeList() // ERROR
, mà tôi không đúng cách giải thích và Danh sách [Bất kỳ] vì trả lại một Danh sách trống rỗng, nhưng Ken gọi nó ra:
List(0)
không tạo ra một danh sách với 0 tố.
Nó tạo ra một List[Int]
chứa một phần tử (giá trị 0).
Do đó, List[Int]
trên một nhánh có điều kiện và List[String]
trên nhánh có điều kiện khác tổng quát thành List[Any]
.
Trong trường hợp này, typer không quá chung chung - đó là lỗi trong mã.
)
Như một vấn đề của (phong cách cá nhân của tôi), tôi cung cấp cho các loại lợi nhuận rõ ràng cho tất cả nhưng những phương pháp đơn giản nhất (về cơ bản, một lớp lót với không có logic có điều kiện). Hãy nhớ rằng nếu bạn để trình biên dịch suy ra loại kết quả của phương thức, nó có thể cụ thể hơn bạn muốn. (Ví dụ: 'HashMap' thay vì' Bản đồ'.) –
@Randall có, điểm tốt (về kiểu trả về quá cụ thể). – Jesper