Bạn có thể xác định loại trực tiếp vào phương pháp empty
thay vì phải thêm các thiết lập thêm dấu ngoặc/niềng răng và loại chú thích:
class Bar[A](set: Set[Foo[A]] = Set.empty[Foo[A]])
Đối với lý do tại sao những suy luận kiểu thất bại, thấy những câu hỏi này :
Cập nhật:
Tôi xin lỗi, câu trả lời vội vàng của tôi đã hết. Vấn đề trong bài viết ở trên không thực sự liên quan đến vấn đề này. @TravisBrown thực hiện một điểm rất tốt trong bình luận của mình ở trên. Điều này dường như làm việc lúc đầu:
class Bar[A](set: Set[A] = Set.empty)
Nhưng nếu bạn thực sự cố gắng để gọi các nhà xây dựng nó không thành công tại sử dụng tại chỗ:
new Bar[Int]
// <console>:9: error: type mismatch;
// found : scala.collection.immutable.Set[Nothing]
// required: Set[Int]
// Note: Nothing <: Int, but trait Set is invariant in type A.
// You may wish to investigate a wildcard type such as `_ <: Int`. (SLS 3.2.10)
// Error occurred in an application involving default arguments.
// new Bar[Int]
Điều này cho thấy trình biên dịch không buộc các tham số mặc định để có giá trị cho tất cả A
, chỉ dành cho một số A
. Họ có thể chọn như vậy, do đó bạn có thể làm một cái gì đó như thế này:
scala> case class MyClass[T](set: Set[T] = Set(0))
defined class MyClass
scala> MyClass() // defaults to MyClass[Int]
res0: MyClass[Int] = MyClass(Set(0))
scala> MyClass(Set('x)) // but I can still use other types manually
res1: MyClass[Symbol] = MyClass(Set('x))
Tuy nhiên, bất kỳ loại lồng với kiểu tham số không gõ kiểm tra tại địa điểm khai trong các nhà xây dựng:
class Bar[A](set: Set[Option[A]] = Set.empty)
// <console>:7: error: polymorphic expression cannot be instantiated to expected type;
// found : [A]scala.collection.immutable.Set[A]
// required: Set[Option[?]]
// class Bar[A](set: Set[Option[A]] = Set.empty)
Các suy luận không thất bại nếu các tham số kiểu là ở một vị trí hiệp biến:
class Bar[ A ](set: List[Foo[A]] = List.empty) // OK
class Bar[ A ](set: Map[Int,Foo[A]] = Map.empty) // OK (unless you use it)
class Bar[ A ](set: Map[Foo[A],Int] = Map.empty) // BAD
// <console>:8: error: polymorphic expression cannot be instantiated to expected type;
// found : [A, B]scala.collection.immutable.Map[A,B]
// required: Map[Foo[?],Int]
// class Bar[ A ](set: Map[Foo[A],Int] = Map.empty) // BAD
// ^
những đang làm việc vì trình biên dịch chọn Nothing
như đồng loại biến thể theo mặc định.Điều này làm việc tốt cho List
, nhưng ví dụ thứ hai ở trên không hoạt động nếu bạn thực sự cố gắng gọi nó.
Nguyên nhân gây ra sự kỳ quặc này có lẽ là cách mà Scala xử lý các đối số mặc định. Trình biên dịch tự động thêm một phương thức bổ sung cho đối tượng đồng hành, và sau đó bất cứ nơi nào bạn rời khỏi một đối số, trình biên dịch sẽ tự động thêm một lời gọi phương thức vào phương thức mới trong đối tượng đồng hành để tạo đối số còn thiếu thay thế. Dường như trừu tượng đối số mặc định ra thành một phương thức ngắt một số thứ trong suy luận kiểu sẽ làm việc với một phép gán thông thường.
Tôi nghĩ hầu hết những phát hiện này khá khó hiểu. Những gì tôi lấy đi từ điều này là điều quan trọng là phải thực sự kiểm tra các thông số mặc định của bạn để chắc chắn rằng chúng không phá vỡ độ chính xác của loại khi bạn cố gắng sử dụng chúng!
Không phải là câu trả lời, nhưng ba điều cần lưu ý: bạn có thể muốn đặt tên cho tham số kiểu khác với 'A' để tránh nhầm lẫn với (khác)' A' trong 'scala.collection 'đã tìm thấy. immutable.Set [A] 'message; thực tế quan trọng về cả 'Set' và' Hallo' của bạn là chúng không biến đổi (trái với 'List'); và biên dịch dòng cuối cùng của bạn có thể không làm những gì bạn muốn. –
Trong khi 'lớp Bar [A] (hallo: Hallo [A] = Hallo.apply)' nếu bạn thay đổi nó để sử dụng 'Hallo.apply()' nó hoạt động tốt. Bạn _should_ có thể để lại các parens off, vì vậy nó phải được thực sự bối rối ở đây. Nó cho rằng bạn đang truyền hàm được áp dụng một phần 'Hallo.apply' thay vì gọi' apply' mà không có đối số. (Thông báo lỗi cho biết nó tìm thấy loại '[A]() Hallo [A]'.) – DaoWen