2011-08-22 28 views
75

Clojure có gen-class, reify, proxy và deftype và defrecord để định nghĩa kiểu dữ liệu kiểu lớp mới. Đối với một ngôn ngữ có giá trị đơn giản hóa cú pháp và gây ra sự phức tạp không cần thiết, nó có vẻ giống như một quang sai. Ai đó có thể giải thích lý do tại sao nó như vậy? Có thể phân lớp kiểu Lisp phổ biến có sufficed?Tại sao Clojure có 5 cách để xác định một lớp thay vì chỉ một?

Trả lời

82

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

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

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

cụ thể hóaProxy đều được sử dụng để tự động tạo ra một thể hiện của một lớp vô danh khi chạy. Proxy đã được đưa ra trước, việc sửa đổi đã xuất hiện cùng với deftype và defrecord trong clojure 1.2. Reify được ưu tiên, giống như deftype, nơi ngữ nghĩa không quá hạn chế.

Điều đó đặt câu hỏi về lý do tại sao cả deftype và defrecord, vì chúng xuất hiện cùng một lúc và có vai trò tương tự. Đố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ốt đẹp clojure khác nhau mà chúng ta biết và yêu thương, sequability và vv. Deftype được thiết kế để sử dụng như một khối xây dựng mức thấp để thực hiện các cơ sở 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ủa các trường có thể thay đổi (mặc dù đây không phải là mặc định).

Để đọc thêm kiểm tra:

The clojure.org datatypes page

The google group thread where deftype and reify were introduced

+1

Chuỗi nhóm trên google rất có giá trị. Sự hiểu biết của tôi là dành cho proxy tương tác java, gen-class được thay thế bởi reify và deftype chủ yếu. Tôi rất vui vì chúng tôi có ít cách 'được khuyến nghị' hơn để xác định loại ngay bây giờ. – Salil

+1

Câu trả lời hay và cảm ơn liên kết chuỗi. –

+0

Xin lỗi, "khả năng tuần tự" nghĩa là gì? Google không trợ giúp ... – Trylks

42

Câu trả lời ngắn gọn là tất cả họ đều có mục đích khác nhau và hữu ích. Sự phức tạp là do sự cần thiết phải 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 là gắn bó với bản ghi nhớ hoặc bản đồ Clojure đơn giản.

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

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

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

Flowchart for choosing the right clojure type definition form

+1

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

+3

sự khác biệt không lớn, nhưng chúng * khác biệt 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 phương pháp tiếp cận trong Clojure phản ánh những khác biệt cơ bản, đó là một lý do chính đáng tại sao họ nên được đặt tên khác nhau. – mikera

+0

+1. Đã không nhìn thấy sơ đồ trước đó, đó là tuyệt vời. –

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