Đặc điểm là một cách khác để làm thành phần. Hãy nghĩ về chúng như một cách để tổng hợp tất cả các phần của một lớp trong thời gian biên dịch (hoặc thời gian biên dịch JIT), lắp ráp các triển khai cụ thể của các phần bạn sẽ cần.
Về cơ bản, bạn muốn sử dụng các đặc điểm khi bạn thấy mình tạo các lớp với các kết hợp các tính năng khác nhau. Tình huống này xuất hiện thường xuyên nhất đối với những người viết thư viện linh hoạt cho người khác tiêu thụ. Ví dụ: đây là tuyên bố của một lớp kiểm tra đơn vị tôi đã viết gần đây bằng ScalaTest :
class TestMyClass
extends WordSpecLike
with Matchers
with MyCustomTrait
with BeforeAndAfterAll
with BeforeAndAfterEach
with ScalaFutures
Đơn vị khuôn khổ kiểm tra có một tấn tùy chọn cấu hình khác nhau, và mỗi đội đều có sở thích khác nhau về cách họ muốn làm điều này. Bằng cách đặt các tùy chọn vào các đặc điểm (được trộn lẫn trong sử dụng with
trong Scala), ScalaTest có thể cung cấp tất cả các tùy chọn đó mà không phải tạo tên lớp như WordSpecLikeWithMatchersAndFutures
, hoặc một tấn cờ boolean thời gian chạy như thế nào WordSpecLike(enableFutures, enableMatchers, ...)
. Điều này giúp bạn dễ dàng tuân theo nguyên tắc Mở / Đóng . Bạn có thể thêm các tính năng mới và kết hợp các tính năng mới, chỉ bằng cách thêm một đặc điểm mới. Nó cũng làm cho việc tuân theo Nguyên tắc phân chia giao diện dễ dàng hơn , bởi vì bạn có thể dễ dàng đặt các chức năng không cần thiết vào một đặc điểm chung.
Các đặc điểm cũng là một cách tốt để đặt mã chung vào một số lớp không có ý nghĩa để chia sẻ hệ thống phân cấp thừa kế. Kế thừa là một mối quan hệ gắn bó rất chặt chẽ và bạn không nên trả chi phí đó nếu bạn có thể giúp đỡ. Đặc điểm là một mối quan hệ kết nối lỏng lẻo hơn nhiều. Trong ví dụ của tôi ở trên, tôi đã từng MyCustomTrait
dễ dàng chia sẻ việc triển khai cơ sở dữ liệu giả giữa một số lớp kiểm tra không liên quan.
Việc tiêm phụ thuộc đạt được nhiều mục tiêu giống nhau, nhưng trong thời gian chạy dựa trên đầu vào của người dùng thay vì vào thời gian biên dịch dựa trên đầu vào của lập trình viên. Các đặc điểm cũng được dự định nhiều hơn cho các phụ thuộc là một phần về mặt ngữ nghĩa của cùng một lớp. Bạn sắp xếp các phần của một lớp thay vì thực hiện các cuộc gọi đến các lớp khác với các trách nhiệm khác.
Các khung tiêm phụ thuộc đạt được nhiều mục tiêu giống nhau tại thời điểm biên dịch dựa trên đầu vào của lập trình viên, nhưng phần lớn là một cách giải quyết cho các ngôn ngữ lập trình mà không có sự hỗ trợ đặc điểm thích hợp. Các đặc điểm đưa các phụ thuộc này vào vương quốc của trình kiểm tra loại trình biên dịch, với cú pháp rõ ràng hơn, với quy trình xây dựng đơn giản hơn, giúp phân biệt rõ ràng hơn giữa các phụ thuộc thời gian biên dịch và thời gian chạy.