Tại sao Clojure có 5 cách để định nghĩa một lớp thay vì chỉ một?


84

Clojure có gen-class, reify, proxy và cũng có thể định dạng và gỡ ghi âm để xác định các kiểu dữ liệu giống như lớp mới. Đối với một ngôn ngữ coi trọng sự đơn giản về cú pháp và phản đối sự phức tạp không cần thiết, nó có vẻ như là một sự sai lệch. Ai đó có thể giải thích tại sao nó là như vậy? Liệu phân lớp kiểu Common Lisp có đủ không?

Câu trả lời:


90

Đây là sự kết hợp của ba yếu tố khác nhau:

  1. Hệ thống loại cụ thể của jvm
  2. Nhu cầu về ngữ nghĩa hơi khác nhau cho các trường hợp sử dụng khác nhau khi xác định các loại
  3. Thực tế là một số trong số này đã được phát triển trước đó, và một số muộn hơn, khi ngôn ngữ đã phát triển.

Vì vậy, trước tiên, chúng ta hãy xem xét những gì làm. deftypegen-class giống nhau ở chỗ cả hai đều định nghĩa một lớp được đặt tên để biên dịch trước thời hạn. Gen-class đứng đầu, tiếp theo là deftype in clojure 1.2. Deftype được ưa thích hơn và có các đặc điểm hiệu suất tốt hơn, nhưng hạn chế hơn. Một lớp định dạng có thể tuân theo một giao diện, nhưng không thể kế thừa từ một lớp khác.

Reifyproxy đều được sử dụng để tạo động một phiên bản của lớp ẩn danh trong thời gian chạy. Proxy xuất hiện đầu tiên, sửa đổi đi kèm với định dạng và xóa ghi âm trong clojure 1.2. Reify được ưu tiên hơn, cũng giống như deftype, nơi ngữ nghĩa không quá hạn chế.

Điều đó đặt ra câu hỏi tại sao cả hai định dạng và xóa ghi âm, vì chúng xuất hiện cùng một lúc và có vai trò giống nhau. Đối với hầu hết các mục đích, chúng tôi sẽ muốn sử dụng defrecord: nó có tất cả các tính năng tốt của áo choàng khác nhau mà chúng tôi biết và yêu thích, khả năng tuần tự, v.v. Deftype được thiết kế để sử dụng như một khối xây dựng cấp thấp để triển khai các cấu trúc dữ liệu khác. Nó không bao gồm các giao diện clojure thông thường, nhưng nó có tùy chọn các trường có thể thay đổi (mặc dù đây không phải là mặc định).

Để đọc thêm, hãy xem:

Trang dữ liệu clojure.org

Chuỗi nhóm google nơi giới thiệu định dạng và sửa đổi


1
Chủ đề nhóm google rất có giá trị. Sự hiểu biết của tôi là đối với proxy java-interop, gen-class chủ yếu được thay thế bằng cách sửa đổi và định dạng. Tôi rất vui vì giờ đây chúng ta có ít cách 'được khuyến nghị' hơn để xác định các loại.
Salil

2
@Trylks: Khả năng coi đối tượng như một chuỗi các cặp khóa-giá trị. Khá nhiều thứ có nguồn gốc từ clojure có thể được coi là một chuỗi, điều này rất mạnh mẽ.
Rob Lachlan

proxyđôi khi được ưa thích hơn vì nó cho phép sửa đổi các phương thức trong thời gian chạy. (ví dụ: The Joy of Clojure , ấn bản thứ 2. gợi ý rằng điều này có thể hữu ích cho việc sửa đổi lệnh gọi lại trong trình xử lý web.)
Mars

52

Câu trả lời ngắn gọn là chúng đều có những mục đích hữu ích và khác nhau. Sự phức tạp là do nhu cầu tương tác hiệu quả với các tính năng khác nhau của JVM cơ bản.

Nếu bạn không cần bất kỳ tương tác Java nào thì 99% thời gian bạn tốt nhất nên gắn bó với bản đồ khử ghi âm hoặc bản đồ Clojure đơn giản.

  • Sử dụng defrecord nếu bạn muốn sử dụng các giao thức
  • Nếu không, một bản đồ Clojure thông thường có lẽ là đơn giản và dễ hiểu nhất

Nếu nhu cầu của bạn phức tạp hơn, thì sơ đồ sau là một công cụ tuyệt vời để giải thích lý do tại sao bạn chọn một trong những tùy chọn này thay vì những tùy chọn khác:

http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

Lưu đồ để chọn đúng mẫu định nghĩa loại áo choàng


1
cảm ơn rất nhiều cho liên kết đến lưu đồ. Điều này giúp ích cho blog là của đồng tác giả của O’reilly's - Lập trình Clojure. Tôi nghĩ việc ra quyết định này khá phức tạp. Có phải sự khác biệt giữa giao diện và lớp cụ thể hoặc cần xác định các phương thức tĩnh hay không hoặc kiểu được đặt tên hoặc kiểu ẩn danh quá lớn đến mức chúng cần một cấu trúc ngôn ngữ khác?
Salil

4
sự khác biệt không quá lớn, nhưng chúng khác nhau về mặt triết học về những gì bạn đang cố gắng đạt được. Tôi nghĩ rằng nhiều cách tiếp cận trong Clojure phản ánh những khác biệt cơ bản này, đó là lý do chính đáng tại sao chúng nên được đặt những tên khác nhau.
mikera

Lưu đồ rất tuyệt, nhưng không bao gồm tất cả các khả năng hoặc lý do sử dụng một hoặc một tùy chọn khác, hoặc kết hợp chúng. Không có biểu đồ đơn giản nào có thể.
Sao Hỏa
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.