Hàm tạo riêng và được bảo vệ trong Scala


109

Tôi đã rất tò mò về tác động của việc không có một hàm tạo chính rõ ràng trong Scala, mà chỉ là nội dung của phần thân lớp.

Đặc biệt, tôi nghi ngờ rằng mẫu phương thức khởi tạo riêng tư hoặc được bảo vệ, nghĩa là, điều khiển việc xây dựng thông qua đối tượng đồng hành hoặc các phương thức của lớp hoặc đối tượng khác có thể không có triển khai rõ ràng.

Liệu tôi có sai? Nếu vậy, làm thế nào nó được thực hiện?


Bạn có thể có một singleton Scala (nghĩa là với từ khóa object), và xác định lớp của bạn là private bên trong singleton đó và có các phương thức của singleton để xây dựng các đối tượng của bạn.
Paggas

@Paggas, thật không may khi bạn trả về một thể hiện của lớp được đánh dấu là private ngoài phạm vi của nó, nó sẽ không biên dịch, ngay cả khi được trả về từ một phương thức của nó trong đối tượng đồng hành phạm vi.
Don Mackenzie

Điều này được thực hiện khá kỹ lưỡng trong suốt mã nguồn Scalaz. Khái niệm này còn được gọi là một kiểu dữ liệu đại số trừu tượng .
Tony Morris

Câu trả lời:


190

Bạn có thể khai báo hàm tạo mặc định là private / protected bằng cách chèn từ khóa thích hợp giữa tên lớp và danh sách tham số, như sau:

class Foo private () { 
  /* class body goes here... */
}

Cảm ơn Aleksander, Bạn có thể vui lòng cho tôi biết điều này được trình bày trong một trong những cuốn sách scala hay trong đặc tả ngôn ngữ không? Xin lỗi, tôi chưa thể ủng hộ.
Don Mackenzie

Tôi chỉ lướt qua phần giải thích của "Lập trình Scala" về các hàm tạo (trang 92-95) và tôi không thấy nó được đề cập ở đó. Tôi thực sự đã tìm thấy câu trả lời cho câu hỏi của bạn trong một bảng thay đổi cũ, nhưng tôi chưa bao giờ thấy nó được đề cập ở bất kỳ nơi nào khác trước đây. Liên kết: scala-lang.org/node/43#2.4.0
Aleksander Kmetec

18
Trang 414 của "Lập trình trong Scala". Trang 97 của Wampler's Programming Scala. Trang 60 của Subramaniam's Programming Scala. Hiện tôi chưa có bản PDF của Beginning Scala để xem thử.
Daniel C. Sobral

Ồ, tôi thấy nó bây giờ ở trang 97. Cảm ơn.
Aleksander Kmetec

1
Cảm ơn cả hai vì đã nghiên cứu thêm, tôi đã có cuốn sách của Wampler, nhưng chỉ trên điện thoại của tôi và rõ ràng là tôi chưa đọc kỹ nhưng tôi thấy rằng nó bổ sung cho cuốn sách Odersky một cách đáng ngạc nhiên.
Don Mackenzie

64

Câu trả lời của Aleksander là đúng, nhưng Lập trình trong Scala cung cấp một giải pháp thay thế bổ sung:

sealed trait Foo {
 // interface
}

object Foo {
  def apply(...): Foo = // public constructor

  private class FooImpl(...) extends Foo { ... } // real class
}

18
Nhiều năm sau, tôi nghĩ đây là một câu trả lời hay cho câu hỏi nhưng lại là một giải pháp tồi cho vấn đề. Nếu một lập trình viên tương lai nào đó sử dụng mã của Aleksander, anh ta sẽ nói "À, hàm tạo chính là private nhưng các hàm tạo khác thì không." Nếu lập trình viên đó nhìn vào mã của Daniel, anh ta sẽ nói, "À, họ đang sử dụng mẫu Factory để bù đắp cho việc Scala không thể đánh dấu các hàm tạo mặc định là riêng tư. Chờ đã, Scala có thể đánh dấu các hàm tạo mặc định là riêng tư! Chuyện gì đang xảy ra trên đây?!? " Nói cách khác, một tỷ lệ WTF / LOC xấu.
Malvolio

20
@Malvolio Tôi không hoàn toàn đồng ý. Mẫu này không chỉ làm cho phương thức khởi tạo chính trở nên riêng tư mà còn là quá trình thực thi , buộc người dùng phải sử dụng giao diện (đặc điểm). Điều đó có giá trị riêng của nó. Còn đối với việc ai đó đang nghĩ gì đó vì anh ấy / cô ấy không biết ngôn ngữ đó - piffle! Để trích dẫn Kenny Tilton, hãy học ngôn ngữ chết tiệt !
Daniel C. Sobral,

7
Ở đâu đó cần đề cập rằng cách tiếp cận này có nghĩa là không sử dụng newtừ khóa.
Travis Parks

1
Một lưu ý với cách tiếp cận này là ai đó vẫn có thể tạo Foo thông qua việc triển khai của chính họ. Đó có thể được xem là thuận lợi hay khó khăn tùy thuộc vào lý do kiểm soát thi công.
aij 19/12/13

1
@aij Đúng, vì vậy tôi chỉ làm cho nó không thể xảy ra nữa. :)
Daniel C. Sobral
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.