Gói phương thức trả về null trong Java với Option trong Scala?


107

Giả sử tôi có một phương thức session.get(str: String): Stringnhưng bạn không biết liệu nó sẽ trả về cho bạn một chuỗi hay một null, bởi vì nó đến từ Java.

Có cách nào dễ dàng hơn để điều trị điều này trong Scala thay vì session.get("foo") == null? Có thể một số phép thuật áp dụng như thế ToOption(session.get("foo"))và sau đó tôi có thể xử lý nó theo cách Scala như

ToOption(session.get("foo")) match {
    case Some(_) =>;
    case None =>;
}

4
Để biết thêm các thủ thuật về Option, hãy xem blog.tmorris.net/scalaoption-cheat-sheet
Landei

4

Câu trả lời:


182

Các Optionđối tượng đồng hành của applyphương pháp đóng vai trò như một chức năng chuyển đổi từ tài liệu tham khảo nullable:

scala> Option(null)
res4: Option[Null] = None

scala> Option(3)   
res5: Option[Int] = Some(3)

19

Đối Optiontượng có một applyphương thức thực hiện chính xác điều đó:

var myOptionalString = Option(session.get("foo"));

5

Lưu ý rằng khi làm việc với các đối tượng Java, nó sẽ không hoạt động như mong đợi:

val nullValueInteger : java.lang.Integer = null
val option: Option[Int] = Option(nullValueInteger)
println(option)  // Doesn't work - zero value on conversion

val nullStringValue : String = null
val optionString: Option[String] = Option(nullStringValue)
println(optionString) // Works - None value

1
Tôi đã chạy với scala 2.11.8. Dòng thứ hai ném NullPointerException. Dòng thứ sáu có Some (null), không phải None như bạn mong đợi.
John Lin

1. Được sử dụng Some thay vì Option trong optionString - Đã thay đổi trong câu trả lời ban đầu. 2. Chỉ được xác minh trong Scala 2.12.5
DekelM

-3

Đây là một chủ đề rất cũ nhưng là một chủ đề hay!

Đúng là việc chuyển đổi bất kỳ kết quả Không ngoại lệ nào của Try to Option sẽ dẫn đến một số ...

scala> Try(null).toOption
res10: Option[Null] = Some(null)

... bởi vì Thử không phải về kiểm tra tính vô hiệu mà chỉ là một cách để xử lý các ngoại lệ về mặt chức năng.

Việc sử dụng Cố gắng bắt một ngoại lệ và chuyển đổi thành Tùy chọn để thuận tiện sẽ chỉ hiển thị Không có trong trường hợp ngoại lệ xảy ra.

scala> Try(1/0).toOption
res11: Option[Int] = None

Bạn muốn bảo tồn các giá trị có được từ Thử. Đó có thể là giá trị không.

Nhưng cũng đúng là lib tiêu chuẩn đôi khi khá khó hiểu ...

scala> Try(null).toOption
res12: Option[Null] = Some(null)

scala> Option(null)
res13: Option[Null] = None

Hành vi này hơi mâu thuẫn nhưng nó phản ánh cách sử dụng có chủ đích của cả Try và Option.

Bạn sử dụng cố gắng lấy bất cứ điều gì xuất hiện từ một biểu thức có thể tạo ra các ngoại lệ và bạn không quan tâm đến chính ngoại lệ đó.

Giá trị có thể xuất hiện rất có thể là giá trị rỗng. Nếu toOption đưa ra Không có, bạn không thể phân biệt giữa ngoại lệ và null , và điều đó không đẹp!

Độc lập, bạn sử dụng Option để gói gọn sự tồn tại hay không của một thứ gì đó. Vì vậy, trong trường hợp đó Some (null) là Không có, và điều đó có ý nghĩa, bởi vì null trong trường hợp đó đại diện cho sự vắng mặt của một cái gì đó. Không có sự mơ hồ ở đây.

Điều quan trọng cần lưu ý là trong mọi trường hợp, tính minh bạch của tham chiếu không bị phá vỡ vì .toOption không giống như Option ()

Nếu bạn thực sự cần thực thi cả an toàn ngoại lệ an toàn null, và mã của bạn thực sự không cần phân biệt giữa null và ngoại lệ , bạn chỉ cần kết hợp cả hai mô hình! Bởi vì tốt, đó là những gì bạn muốn, phải không?

Bạn có thể làm điều đó bằng một cách ...

scala> Try(Option(null)).getOrElse(None)
res23: Option[Null] = None

scala> Try(Option(3/0)).getOrElse(None)
res24: Option[Int] = None

scala> Try(Option(3)).getOrElse(None)
res25: Option[Int] = Some(3)

... hay cách khác ...

scala> Try(Option(null)).toOption.flatten
res26: Option[Null] = None

scala> Try(Option(3/0)).toOption.flatten
res27: Option[Int] = None

scala> Try(Option(3)).toOption.flatten
res28: Option[Int] = Some(3)

... hoặc người xấu xí nhất trong số họ ...

scala> Option(Try(null).getOrElse(null))
res29: Option[Null] = None

scala> Option(Try(3/0).getOrElse(null))
res30: Option[Any] = None

scala> Option(Try(3).getOrElse(null))
res31: Option[Any] = Some(3)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.