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
Đây là một kết hợp của ba yếu tố khác nhau:
- Hệ thống loại hình cụ thể của JVM
- 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
- 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. deftype và gen-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óa và Proxy đề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
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/
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
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
+1. Đã không nhìn thấy sơ đồ trước đó, đó là tuyệt vời. –
- 1. Chỉ định một gói thay vì "classesToBeBound" cho spring Jaxb2Marshaller
- 2. cách xác định một lớp chỉ trong một dòng?
- 3. Tại sao tôi cần chuyển một DataView (thay vì chỉ một DataTable) sang PieChart.draw()?
- 4. Tại sao chỉ có một lớp cho mỗi tập tin
- 5. Tại sao áp dụng() ở đây chỉ có một đối số thay vì hai đối số?
- 6. Tại sao sử dụng singleton thay vì lớp tĩnh?
- 7. Tại sao 'được xác định() || xác định 'cú pháp trong việc xác định một hằng số
- 8. Tại sao NDEBUG thay vì RELEASE?
- 9. Tại sao một số trang web sử dụng jquery với $ j thay vì chỉ là $?
- 10. Tại sao `this.synchronized` thay vì chỉ` đồng bộ` trong Scala?
- 11. Tại sao sử dụng var thay vì tên lớp?
- 12. Biến lớp được định nghĩa tại @implementation thay vì @interface?
- 13. Tại sao ArrayList không có getSize() thay vì size()?
- 14. Tại sao FloatBuffer thay vì phao []?
- 15. Trong Clojure tại sao sử dụng: chỉ []
- 16. Tại sao các đại biểu UIKit "chỉ định" thay vì "yếu"?
- 17. Tại sao một maven-war-plugin tạo ra một JAR thay vì một WAR?
- 18. Tại sao quá tải đúng và sai thay vì xác định toán tử bool?
- 19. Tại sao testFixture thay vì TestClass?
- 20. Clojure: xác định xem hàm có tồn tại
- 21. Tại sao kiểu dữ liệu Data.String.IsString chỉ xác định một chuyển đổi?
- 22. Tại sao CHỌN 0, ... thay vì CHỌN
- 23. Tại sao putchar, toupper, tolower, vv lấy một int thay vì một char?
- 24. Tại sao có macro xác định _tmain?
- 25. Thanh xếp hạng chỉ hiển thị một nửa sao thay vì sao đầy đủ
- 26. Tại sao nhập javax.swing. * Thay vì java.swing. *
- 27. Xác định Clojure multimethods
- 28. Tại sao std :: cout thay vì chỉ đơn giản là cout?
- 29. Tại sao phải đồng bộ hóa trên một thành viên khóa tĩnh thay vì trên một lớp học?
- 30. Tại sao chặn thay vì lặp?
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
Câu trả lời hay và cảm ơn liên kết chuỗi. –
Xin lỗi, "khả năng tuần tự" nghĩa là gì? Google không trợ giúp ... – Trylks