2011-06-21 40 views
7

tôi cần phải ghi đè lên các phương pháp Java sau trong một lớp học Scala:Scala: Ghi đè một Generic Phương pháp Java mà trả về null

public class Test<T> { 
    public T test(T o, boolean x) { 
     if (x) { 
      return o; 
     } 
     return null; 
    } 
} 

Với phương pháp sau đây (trong Scala), trình biên dịch phàn nàn, "Biểu hiện của loại Null không phù hợp với mong đợi kiểu T ":

class Test2[T] extends Test[T] { 
    override def test(o: T, x: Boolean): T = { 
    if (x) { 
     return o 
    } 
    return null 
    } 
} 

tôi cũng đã cố gắng để xác định Option[T] như giá trị trả về, nhưng sau đó một lần nữa, trình biên dịch phàn nàn rằng chữ ký phương pháp sẽ không khớp.

Bất kỳ ý tưởng nào? - Cảm ơn!


Edit:

đề nghị Daniel làm việc cho các vấn đề như gửi ban đầu; Tuy nhiên, tôi thực tế vấn đề không may vẫn hơi khác (bằng cách tham số kiểu generic trong phương pháp, không lớp, định nghĩa) (xin lỗi):

Java:

public class Test { 
    public <T> T test(T o, boolean x) { 
     if (x) { 
      return o; 
     } 
     return null; 
    } 
} 

Scala:

class Test2 extends Test { 
    override def test[T >: Null](o: T, x: Boolean): T = { 
    if (x) { 
     return o 
    } 
    return null 
    } 
} 

Lập lại lỗi không thành công, "Biểu thức loại Null không phù hợp với loại T mong đợi".
(Tôi tin rằng đó là bởi vì override không bao gồm bất kỳ khả năng - tức là, một cái gì đó kiểu Nothing có thể được truyền cho Test.test(..) - tốt, có thể nó ;-))

gì làm việc là ném một RuntimeException thay vì trả lại null như Ricky đã đề xuất; tuy nhiên, tôi sẽ rất biết ơn cho đầu vào thêm.

Cảm ơn tất cả!

Trả lời

12

Bạn cần điều này:

class Test2[T >: Null] extends Test[T] { 

Vấn đề là rằng Nothing không thể null, và, là subtype của tất cả mọi thứ, đó là một giá trị hợp lệ của T. Vì vậy, bạn cần phải chỉ định Null làm giới hạn dưới.

EDIT

Thật không may, không có cách nào tốt xung quanh vấn đề thực tế của bạn. Trong trường hợp này, bạn sẽ phải viết null.asInstanceOf[T] và để nó ở đó.

Và, có, bạn có thể gọi bằng các loại không thể vô hiệu. Hãy thử điều này, ví dụ:

object Test3 { 
    val test = new Test(); 
    val x: Int = test.test(5, false); 
} 
+0

Đó là giải pháp hoàn hảo cho vấn đề như ban đầu được đăng; tuy nhiên, tôi phải tìm ra rằng vấn đề thực tế hơi khác. - Tôi sẽ đánh dấu đây là giải pháp nếu không có câu trả lời chính xác hơn, nhưng bạn có thể vui lòng xem lại một lần nữa trong câu hỏi - hiện đã được chỉnh sửa hay không. - Cảm ơn rất nhiều. – robbbert

+0

Cảm ơn, tốt lắm. - Cả hai giải pháp làm việc (thứ hai sử dụng '[T]' như tham số kiểu), mặc dù tôi chưa hiểu rõ vấn đề ... – robbbert

+0

@robbbert Tìm kiếm thông tin về 'Nothing' và' Null' để hiểu nó tốt hơn . –

6

T là không hạn chế, vì vậy nó có thể được bất kỳ loại bao gồm Int, Double, Float hoặc phân nhóm khác của AnyVal mà không thể null.

Bạn có thể muốn lớp Test2[T <: AnyRef] chứ không phải là lớp Test[T], tuyên bố rằng T là bất kỳ loại đó là AnyRef (về cơ bản java.lang.Object) hoặc bất kỳ kiểu phụ đó.

Nói chung, hãy cố gắng trả về một cái gì đó hữu ích hơn null hoặc ném một ngoại lệ. Có thể có trường hợp bạn phải làm điều đó vì một số API của bên thứ ba, nhưng nếu không phải như vậy, hãy xem liệu có cách nào tốt hơn không. null không xuất hiện trong loại của phương thức, trong khi Option không, ví dụ.

+0

Đó là những gì tôi nghĩ, nhưng ' def z [T <: AnyRef]: T = null' vẫn không biên dịch. – kassens

+0

'lớp Test2 [T <: AnyRef] mở rộng Kiểm tra [T]' nên biên dịch tốt –

+0

@oxbow_lakes Không, nó không, câu trả lời của Daniel là chính xác. – kassens

0

Bạn đã xem là sử dụng lựa chọn thay vì sau sẽ làm việc:

class Test{ 
    def test[T] (value:T,flag :Boolean) :Option[T] = { 
    if (flag){ 
     Some(value) 
    }else{ 
     None 
    } 
    } 
} 

Nó sẽ giúp phân biệt những tình huống như test(null,true)test(null,false)

+0

Cảm ơn, nhưng (như đã đề cập trong câu hỏi ban đầu) đó là chữ ký phương thức khác với phương thức được ghi đè. – robbbert

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