Nếu tính trạng A kéo dài B, thì việc trộn vào A cung cấp cho bạn chính xác B cộng với bất cứ điều gì A thêm hoặc kéo dài. Ngược lại, nếu tính trạng A có một tham chiếu tự được gõ rõ ràng là B, thì lớp cha cuối cùng cũng phải trộn vào B hoặc một kiểu con cháu của B (và trộn nó trước , điều này rất quan trọng).
Đó là sự khác biệt quan trọng nhất. Trong trường hợp đầu tiên, loại B chính xác được kết tinh tại điểm A mở rộng nó. Trong lần thứ hai, người thiết kế lớp cha sẽ quyết định phiên bản B nào được sử dụng, tại điểm mà lớp cha được tạo.
Một sự khác biệt khác là nơi A và B cung cấp các phương thức cùng tên. Trong đó A mở rộng B, phương thức của A ghi đè B's. Khi A được trộn sau B, phương thức của A đơn giản là thắng.
Tham chiếu tự đánh máy cho bạn tự do hơn nhiều; khớp nối giữa A và B bị lỏng.
CẬP NHẬT:
Vì bạn không rõ về lợi ích của những khác biệt này ...
Nếu bạn sử dụng thừa kế trực tiếp, thì bạn tạo đặc điểm A là B + A. Bạn đã thiết lập mối quan hệ trong đá.
Nếu bạn sử dụng một tham chiếu tự đánh máy, thì bất cứ ai muốn sử dụng đặc điểm A của bạn trong lớp C đều có thể
- Trộn B rồi A vào C.
- Trộn một kiểu con của B rồi A vào C.
- Trộn A vào C, trong đó C là lớp con của B.
Và đây không phải là giới hạn của các tùy chọn của họ, theo cách Scala cho phép bạn khởi tạo một đặc điểm trực tiếp với một khối mã làm hàm tạo của nó.
Về sự khác biệt giữa chiến thắng của phương pháp A , bởi vì A được trộn lẫn sau cùng, so với A mở rộng B, hãy xem xét điều này ...
Khi bạn trộn trong một chuỗi các tính trạng, bất cứ khi nào phương thức foo()
được gọi, trình biên dịch sẽ đi đến đặc điểm cuối cùng được trộn vào để tìm kiếm foo()
, sau đó (nếu không tìm thấy), nó đi qua chuỗi bên trái cho đến khi tìm thấy một đặc điểm thực hiện foo()
và sử dụng cái đó. A cũng có tùy chọn để gọi super.foo()
, nó cũng đi qua chuỗi bên trái cho đến khi nó tìm thấy một triển khai, v.v.
Vì vậy, nếu A có bản tự tham chiếu đến B và người viết của A biết rằng B thực hiện foo()
, A có thể gọi super.foo()
biết rằng nếu không có gì khác cung cấp foo()
, B sẽ. Tuy nhiên, người tạo ra lớp C có tùy chọn loại bỏ bất kỳ đặc điểm nào khác trong đó thực hiện foo()
và thay vào đó A sẽ nhận được điều đó.
Một lần nữa, đây là mạnh hơn rất nhiều và ít hạn chế hơn so với A mở rộng B và trực tiếp gọi phiên bản của B foo()
.