Câu hỏi Tập quán của Null / Nothing / Unit ở Scala


Tôi vừa mới đọc: http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

Trong khả năng hiểu biết của tôi, Null là một đặc điểm và trường hợp duy nhất của nó là null.

Khi một phương thức lấy một đối số Null, thì chúng ta chỉ có thể truyền nó Null tham chiếu hoặc null trực tiếp, nhưng không phải bất kỳ tham chiếu nào khác, ngay cả khi nó là null (nullString: String = null ví dụ).

Tôi tự hỏi trong trường hợp sử dụng điều này Null đặc điểm có thể hữu ích. Ngoài ra còn có đặc điểm Không có gì mà tôi không thực sự thấy thêm bất kỳ ví dụ nào.


Tôi thực sự không hiểu sự khác biệt giữa việc sử dụng Nothing và Unit như một kiểu trả về là gì, vì cả hai không trả về bất kỳ kết quả nào, làm cách nào để biết cái nào sẽ sử dụng khi tôi có phương thức thực hiện ghi nhật ký chẳng hạn?


Bạn có tập quán của đơn vị / Null / Không có gì là một cái gì đó khác hơn là một loại trả lại?


76
2018-04-23 15:34


gốc




Các câu trả lời:


Bạn chỉ sử dụng Nothing nếu phương thức không bao giờ trả về (có nghĩa là nó không thể hoàn thành bình thường bằng cách quay trở lại, nó có thể ném một ngoại lệ). Không có gì là không bao giờ instantiated và là có cho lợi ích của hệ thống loại (để trích dẫn James Iry: "Lý do Scala có một loại dưới cùng được gắn với khả năng thể hiện sự khác biệt trong các tham số kiểu."). Từ bài viết bạn đã liên kết tới:

Một cách sử dụng khác của Nothing là một kiểu trả về cho các phương thức không bao giờ   trở về. Điều đó có nghĩa nếu bạn nghĩ về nó. Nếu phương thức trả về   loại là Không có gì, và có tồn tại hoàn toàn không có ví dụ của Không có gì,   thì một phương pháp như vậy không bao giờ được trả lại.

Phương thức ghi nhật ký của bạn sẽ trả về Đơn vị. Có một đơn vị giá trị để nó thực sự có thể được trả về. Từ Tài liệu API:

Đơn vị là một loại phụ của scala.AnyVal. Chỉ có một giá trị của loại   Đơn vị, () và không được đại diện bởi bất kỳ đối tượng nào trong cơ sở   hệ thống thời gian chạy. Một phương thức có kiểu trả về Đơn vị tương tự với một Java   phương thức được khai báo vô hiệu.


65
2018-04-23 15:40



Cảm ơn, bởi "không bao giờ trả về" bạn có nghĩa là cuộc gọi đang chặn vô thời hạn (ví dụ như phương thức khởi động của công cụ lập lịch biểu công việc?) - Sebastien Lorber
@Sabastien: nó không trở lại bình thường, nó có thể ném một ngoại lệ (xem james-iry.blogspot.com/2009/08/…). nếu cuộc gọi chặn chỉ kết thúc bằng việc ném một ngoại lệ thì điều đó sẽ được tính. cảm ơn câu hỏi, điều này cần làm rõ. - Nathan Hughes


Bài viết bạn trích dẫn có thể gây hiểu nhầm. Các Null loại có khả năng tương thích với Máy ảo Javavà Java nói riêng.

Chúng ta phải xem xét điều đó Scala:

  • hoàn toàn hướng đối tượng: mọi giá trị là một đối tượng
  • được nhập mạnh: mọi giá trị phải có loại
  • cần xử lý null tài liệu tham khảo để truy cập, ví dụ, các thư viện và mã Java

do đó, nó trở nên cần thiết để xác định một loại cho null giá trị, là Null đặc điểm, và có null là trường hợp duy nhất của nó.

Không có gì đặc biệt hữu ích trong Null loại trừ khi bạn là loại hệ thống hoặc bạn đang phát triển trên trình biên dịch. Đặc biệt, tôi không thể thấy bất kỳ lý do hợp lý nào để xác định Null nhập tham số cho một phương thức, vì bạn không thể chuyển bất kỳ thứ gì nhưng null


16
2018-04-23 16:40



đó là sự thật, do đó, cuối cùng không có cách sử dụng khác của Null? - Sebastien Lorber
@SebastienLorber đã chỉnh sửa câu trả lời. Tôi thực sự không thể thấy bất kỳ mức sử dụng nào cho nhà phát triển trung bình. Có thể ai đó khác có thể nghĩ ra điều gì đó hữu ích. - pagoda_5b
Cám ơn vì cái này. Nếu chúng ta biết lý do cho loại điều này, chúng ta hiểu chúng, nếu không chúng ta nhớ chúng. - Sreekar
Null là hữu ích khi bạn có một tham số kiểu và có thể muốn trả về null như trong câu hỏi và câu trả lời này, vì bạn không khuyến khích sử dụng null trong scala, nó hiếm khi xuất hiện, có thể có các tập quán khác trong hệ thống kiểu - Daniel Carlsson


Bạn có tập quán của Unit / Null / Nothing là cái gì khác hơn là   loại trả về?


Unit có thể được sử dụng như thế này:

def execute(code: => Unit):Unit = {
  // do something before
  code
  // do something after
}

Điều này cho phép bạn truyền vào một khối mã tùy ý được thực thi.


Null có thể được sử dụng làm loại dưới cùng cho bất kỳ giá trị nào có thể vô hiệu. Một ví dụ là:

implicit def zeroNull[B >: Null] =
    new Zero[B] { def apply = null }

Nothingđược sử dụng trong định nghĩa của None

object None extends Option[Nothing]

Điều này cho phép bạn chỉ định None cho bất kỳ loại Option bởi vì Nothing 'mở rộng' mọi thứ.

val x:Option[String] = None

14
2018-04-23 16:40



Được. Đối với việc sử dụng Đơn vị của bạn, bạn có thể đã sử dụng một kiểu chung để thực thi có thể trả về kiểu chung này nếu khối mã của bạn trả về cái gì đó khác với đơn vị. - Sebastien Lorber
Như @drexin đã nói trong một bình luận về một câu trả lời khác, nó chủ yếu được sử dụng để biểu thị một tác dụng phụ. - EECOLOR


Tôi chưa bao giờ thực sự sử dụng Null loại, nhưng bạn sử dụng Unit, nơi bạn sử dụng java void. Nothing là một loại đặc biệt, bởi vì như Nathan đã đề cập, có thể không có trường hợp Nothing. Nothing được gọi là kiểu dưới cùng, có nghĩa là, đó là loại phụ của bất kỳ loại nào khác. Điều này (và tham số kiểu contravariant) là lý do tại sao bạn có thể thêm bất kỳ giá trị nào vào Nil - mà là một List[Nothing] - và danh sách sau đó sẽ thuộc loại yếu tố này. None cũng nếu loại Option[Nothing]. Mọi nỗ lực truy cập các giá trị bên trong một vùng chứa như vậy sẽ ném một ngoại lệ, bởi vì nó là cách hợp lệ duy nhất để trả về từ một phương thức kiểu Nothing.


5
2018-04-23 15:50



cảm ơn tôi không biết rằng Không có mở rộng Tùy chọn [Không có gì]. Nó có ý nghĩa trong một số sử dụng generics, nơi một subtype có thể sử dụng Không có gì (tôi đoán thật khó để tìm một ví dụ cho Null và Unit ...) - Sebastien Lorber
Đơn vị được sử dụng, nơi xảy ra tác dụng phụ, ví dụ: đơn nguyên IO có thể thuộc loại IO[Unit] để in trên bàn điều khiển và các loại tương tự. - drexin
Có, không bao giờ được sử dụng đơn nguyên IO nó có ý nghĩa để sử dụng nó với đơn vị (và có lẽ không có gì nếu nó là một số hoạt động IO sản xuất một dòng vô hạn?) - Sebastien Lorber
Không, không có gì không có ý nghĩa ở đó. - drexin


nếu bạn dùng Nothing, không có việc cần làm (bao gồm bảng điều khiển in) nếu bạn làm điều gì đó, hãy sử dụng kiểu đầu ra Unit

object Run extends App {
  //def sayHello(): Nothing = println("hello?")
  def sayHello(): Unit = println("hello?")
  sayHello()
}

... sau đó làm thế nào để sử dụng Nothing?

trait Option[E]
case class Some[E](value: E) extends Option[E]
case object None extends Option[Nothing]

5
2018-04-07 04:35



Cũng thế, E bên trong Option phải ở trong vị trí biến đổi: trait Option[+E] để cho phép những thứ như val x: Option[Int] = None - vim


Không có gì thường được sử dụng ngầm. Trong đoạn mã dưới đây,      val b: Boolean = if (1 > 2) false else throw new RuntimeException("error") các khác mệnh đề là loại Không có gì, là một phân lớp của Boolean (cũng như bất kỳ AnyVal nào khác). Do đó, toàn bộ nhiệm vụ là hợp lệ cho trình biên dịch, mặc dù khác khoản không thực sự trở lại bất cứ điều gì.


2
2018-06-29 23:34





Đây là một ví dụ về Nothing từ scala.predef:

  def ??? : Nothing = throw new NotImplementedError

Trong trường hợp bạn không quen thuộc (và các công cụ tìm kiếm không thể tìm kiếm trên đó) ??? là chức năng giữ chỗ của Scala cho bất kỳ thứ gì chưa được triển khai. Giống như Kotlin TODO.

Bạn có thể sử dụng cùng một thủ thuật khi tạo các đối tượng giả: ghi đè các phương thức không sử dụng với một tùy chỉnh notUsed phương pháp. Ưu điểm của việc không sử dụng ??? là bạn sẽ không nhận được cảnh báo biên dịch cho những điều bạn không bao giờ có ý định triển khai.


0
2018-06-06 22:09