ví dụ tôi cần truy cập tệp kê khai trong hàm def a[A:ClassManifest]
để xóa lớp xóa. Tôi có thể sử dụng chức năng Predef.implicitly nhưng trong trường hợp đó mã của tôi sẽ được miễn là nếu tôi sử dụng đầy đủ hình thức def a[A](implicit b:ClassManifest[A])
. Vì vậy, có những tên được tạo thuận tiện cho những đối số tiềm ẩn đó không?Tôi làm cách nào để truy cập vào "ẩn" tiềm ẩn, nghĩa là xóa [A: B] hoặc xóa [A <% B]?
Trả lời
Có ba phương pháp xác định trước trong Predef
rằng sẽ làm điều đó cho Manifest
s, ClassManifest
s và OptManifest
s: manifest[T]
, classManifest[T]
và optManifest[T]
, tương ứng. Bạn có thể tự viết "các getters ngầm" cho các lớp khác theo cùng một mẫu. Dưới đây là ví dụ manifest[T]
:
def manifest[T](implicit m: Manifest[T]) = m
Vì vậy, dưới đây là cách bạn có thể viết riêng của bạn:
trait UsefulTypeclass[A] {
def info = 42 // sample method
}
// the “implicit getter”
def usefulTypeclass[A](implicit tc: UsefulTypeclass[A]) = tc
// a method that uses the implicit getter
def foo[A: UsefulTypeclass] =
usefulTypeclass[A].info
Như một thủ thuật gọn gàng: nếu bạn đặt tên trình thu thập ngầm "áp dụng" và đặt nó trên đối tượng đồng hành của UsefulTypeclass, bạn có thể sử dụng "UsefulTypeclass [T]" làm giá trị đại diện cho cá thể của typeclass cho T mà không phải nhập gì hơn bản thân typeclass. –
@RM Thủ thuật hay. Tôi đoán nó sẽ có được 'UsefulTypeclass [T]()' (với thêm '()') sau đó. –
Thực ra nó không cần parens. Nếu bạn có (tha thứ cho việc thiếu định dạng) đối tượng TC {def apply [T] (ngầm x: TC [T]) = x}, bạn có thể gọi nó chỉ bằng "TC [SomeClass]" vì "apply" đang được định nghĩa như một phương thức không tham số với một danh sách tham số ẩn, và [SomeClass] làm biến nó thành một tham chiếu đến đối tượng TC. Nó desugars để TC.apply [SomeClass] (theImplicitValue) –
scalap để giải thoát!
Tôi mất mã này:
object TestThing extends App {
def one { println("one") }
def two[T] { println("two") }
def three[T : Manifest] { println("three") }
def four[T: Manifest, U : Manifest] { println("four") }
}
và chạy nó thông qua scalap. Dưới đây là những gì tôi nhận được:
object TestThing extends java.lang.Object with scala.App with scala.ScalaObject {
def this() = { /* compiled code */ }
def one : scala.Unit = { /* compiled code */ }
def two[T] : scala.Unit = { /* compiled code */ }
def three[T](implicit evidence$1 : scala.Predef.Manifest[T]) : scala.Unit = { /* compiled code */ }
def four[T, U](implicit evidence$2 : scala.Predef.Manifest[T], evidence$3 : scala.Predef.Manifest[U]) : scala.Unit = { /* compiled code */ }
}
Như bạn có thể thấy, Tệp kê khai tiềm ẩn đầu tiên được gọi là evidence$1
. Thứ hai và thứ ba— mặc dù ở một phạm vi khác! — được gọi là evidence$2
và evidence$3
. Vì vậy ... đó là cách bạn thực hiện tham chiếu đến Manifests.
Mặc dù vậy, mặc dù, có vẻ hơi đáng sợ với tôi rằng việc xóa một Tệp kê khai cao hơn trong lớp sẽ thay đổi tên của Tệp kê khai có vị trí thấp hơn trong tệp. Tương tự, nó cũng không giúp nhấn mạnh cú pháp của plugin IntelliJ Scala dường như nghĩ rằng các biến Manifest trong phạm vi four()
là evidence$1
và evidence$2
và không nghĩ rằng evidence$3
là một biến hợp lệ ở đó (mặc dù vậy, và evidence$1
thì không). Nhìn chung, có lẽ những điều này nên được lưu ý như là dấu hiệu cảnh báo về việc chơi với các biến Manifest tiềm ẩn?
Bạn luôn có thể khai báo một phương thức có tên nhỏ hơn, nhưng bạn nên _not_ phụ thuộc vào tên ma thuật do Scalac tạo ra. –