2011-01-13 38 views
7

Tôi đang cố gắng sử dụng> =,>, v.v. với DateTime (joda), và cách duy nhất tôi có thể làm cho nó hoạt động chuyển đổiKhông thể cung cấp chuyển đổi ngầm từ DateTime thành Ordered bằng cách sử dụng chuyển đổi ẩn thành Comparable

implicit def dateTime2ordered(x: DateTime): Ordered[DateTime] = 
new Ordered[DateTime] with Proxy { 
    val self = x 

    def compare(y: DateTime): Int = { 
    x.compareTo(y) 
    } 
} 

tôi có vẻ rất muốn một hình thức chung chung hơn như

implicit def comparable2ordered[A <: Comparable[A]](x: A): Ordered[A] = 
    new Ordered[A] with Proxy { 
     val self = x 

     def compare(y: A): Int = { 
     x.compareTo(y) 
     } 
    } 

Nhưng trình biên dịch không thể tìm thấy chuyển đổi này, và sau khi cố gắng gọi nó trực tiếp, tôi đã nhận được thông báo sau tuyên bố rằng DateTime không thuộc loại Comparable [A]. Sau khi kiểm tra nguồn cho DateTime, tôi thấy rằng nó chỉ thực hiện Comparable như một kiểu thô.

tôi đã có thể để có được nó hoạt động sử dụng

implicit def comparable2ordered[A <: Comparable[_]](x: A): Ordered[A] = 
    new Ordered[A] with Proxy { 
     val self = x 

     def compare(y: A): Int = { 
     x.compareTo(y) 
     } 
    } 

Câu hỏi của tôi là: Đây có phải là điều trị Scala đúng đắn về vấn đề này, hoặc các loại ký tự đại diện sẽ bị ràng buộc gây ra các vấn đề trong tương lai với kiểm tra kiểu?

Trả lời

2

Hãy xem, điều này đã tồn tại. Vâng, loại ... Nếu bạn nhìn vào bên trong đối tượng Ordered, trong đó chuyển đổi ngầm được xem xét cho, bạn sẽ tìm thấy điều này:

implicit def orderingToOrdered [T] (x: T)(implicit ord: Ordering[T]) : Ordered[T] 

Vì vậy, miễn là có một Ordering[T] sẵn, người ta có thể tạo ra một Ordered[T]. Bây giờ, để tìm kiếm một Ordering[T] bên trong đối tượng Ordering:

implicit def ordered [A] (implicit arg0: (A) ⇒ Comparable[A]) : Ordering[A] 

Vì vậy, nếu bạn vượt qua một comparable: A with Comparable[A] một cái gì đó mong đợi một Ordered[A], nó sẽ làm điều này:

Ordered.orderingToOrdered(comparable)(Ordering.ordered(Predef.identity(comparable))) 

Giờ đây, khi câu hỏi của bạn : sử dụng các kiểu tồn tại là cách xử lý đúng các kiểu thô Java. Đó là lý thuyết có thể cho điều này để dẫn đến một trật tự không chính xác, nhưng, trong thực tế, rất khó xảy ra. Bạn có thể có vấn đề với sự mơ hồ tiềm ẩn, mặc dù, kể từ Scala đã có một chuyển đổi ẩn Comparable => Ordered, như đã thấy ở trên.

6

Tôi tình cờ gặp câu hỏi này vì tôi cũng đang tìm cách so sánh các đối tượng DateTime joda bằng cách sử dụng toán tử quan hệ.

Câu trả lời của Daniel đã chỉ cho tôi đúng hướng: các đường dẫn có trong scala.math.Ordered sẽ chuyển đổi một cá thể A extends java.lang.Comparable[A] thành Ordered[A] - chúng chỉ cần được đưa vào phạm vi.Cách đơn giản nhất để làm điều này (mà tôi học được here, btw) là với implicitly phương pháp:

val aOrdering = implicitly[Ordering[A]] 
import aOrdering._ 

Việc nắm bắt được rằng org.joda.time.DateTime không mở rộng hoặc thực hiện Comparable chính nó, nó thừa hưởng (gián tiếp) từ org.joda.time.ReadableInstant, mà không mở rộng Comparable. Vì vậy, điều này:

val dateTimeOrdering = implicitly[Ordering[DateTime]] 
import dateTimeOrdering._ 

sẽ không biên dịch, vì DateTime không mở rộng Comparable[DateTime]. Để sử dụng toán tử quan hệ Ordered 's trên một DateTime, bạn phải làm điều này thay vì:

val instantOrdering = implicitly[Ordering[ReadableInstant]] 
import instantOrdering._ 

mà làm việc vì ReadableInstant kéo dài Comparable[ReadableInstant], và chuyển đổi tiềm ẩn trong Ordered có thể chuyển nó sang một Ordered[ReadableInstant].

Cho đến nay, rất tốt. Tuy nhiên, có những tình huống mà một số Ordered[ReadableInstant] không đủ tốt. (Người tôi gặp phải là với ScalaTest của greater and less than Matchers.) Để có được một Ordered[DateTime], tôi đã buộc phải làm điều này:

implicit object DateTimeOrdering extends Ordering[DateTime] { 
    def compare(d1: DateTime, d2: DateTime) = d1.compareTo(d2) 
} 

Nó có vẻ như có nên được một cách dễ dàng hơn, nhưng tôi không thể tìm một ra.

+0

Tôi nghĩ rằng điều này hoạt động: 'import com.github.nscala_time.time.Imports._' – Chris

+0

Vâng, nó hoạt động, nhưng chỉ khi bạn đang sử dụng thư viện thời gian nscala. ;) –

+0

Tôi thích giải pháp "Mở rộng Đặt hàng": ngắn gọn và gọn gàng và giữ "ma thuật" ở mức tối thiểu – Integrator

Các vấn đề liên quan