Tôi thích câu trả lời từ Roland Ewald vì anh ấy đã mô tả với một trường hợp sử dụng bí danh rất đơn giản và để biết thêm chi tiết giới thiệu một hướng dẫn rất hay. Tuy nhiên, vì một trường hợp sử dụng khác được giới thiệu trong bài đăng có tên thành viên loại này , tôi muốn đề cập đến trường hợp sử dụng thực tế nhất của nó, điều mà tôi rất thích: (phần này được lấy từ đây :)
Loại trừu tượng:
type T
T ở trên nói rằng loại này sẽ được sử dụng, chưa được biết và tùy thuộc vào lớp con cụ thể, nó sẽ được xác định. Cách tốt nhất luôn để hiểu các khái niệm lập trình là cung cấp một ví dụ: Giả sử bạn có kịch bản sau:
Ở đây bạn sẽ gặp lỗi biên dịch, bởi vì phương thức eat trong các lớp Cow và Tiger không ghi đè phương thức eat trong lớp Animal, bởi vì các loại tham số của chúng là khác nhau. Đó là Cỏ trong lớp Bò và Thịt trong lớp Hổ so với Thức ăn trong lớp Động vật là siêu hạng và tất cả các lớp con phải tuân thủ.
Bây giờ quay lại kiểu trừu tượng, bằng sơ đồ sau và chỉ cần thêm một kiểu trừu tượng, bạn có thể định nghĩa kiểu đầu vào, theo chính lớp con.
Bây giờ hãy xem các mã sau:
val cow1: Cow = new Cow
val cow2: Cow = new Cow
cow1 eat new cow1.SuitableFood
cow2 eat new cow1.SuitableFood
val tiger: Tiger = new Tiger
cow1 eat new tiger.SuitableFood // Compiler error
Trình biên dịch là hạnh phúc và chúng tôi cải thiện thiết kế của chúng tôi. Chúng ta có thể nuôi bò bằng bò. Phù hợp với thức ăn và trình biên dịch ngăn chúng ta cho bò ăn thức ăn phù hợp với Tiger. Nhưng điều gì sẽ xảy ra nếu chúng ta muốn tạo sự khác biệt giữa loại bò1 Thích hợp Thực phẩm và Bò2 SuitabeFood. Nói cách khác, nó sẽ rất tiện trong một số trường hợp nếu đường dẫn mà chúng ta tiếp cận với loại (tất nhiên thông qua đối tượng) về cơ bản không thành vấn đề. Nhờ các tính năng nâng cao trong scala, có thể:
Các loại phụ thuộc vào đường dẫn: Các
đối tượng Scala có thể có các loại là thành viên. Ý nghĩa của loại, phụ thuộc vào đường dẫn bạn sử dụng để truy cập nó. Đường dẫn được xác định bởi tham chiếu đến một đối tượng (còn gọi là một thể hiện của một lớp). Để thực hiện kịch bản này, bạn cần xác định lớp Grass bên trong Cow, tức là Cow là lớp bên ngoài và Grass là lớp bên trong. Cấu trúc sẽ như thế này:
class Cow extends Animal {
class Grass extends Food
type SuitableFood = Grass
override def eat(food: this.SuitableFood): Unit = {}
}
class Tiger extends Animal {
class Meat extends Food
type SuitableFood = Meat
override def eat(food: this.SuitableFood): Unit = {}
}
Bây giờ nếu bạn cố gắng biên dịch mã này:
1. val cow1: Cow = new Cow
2. val cow2: Cow = new Cow
3. cow1 eat new cow1.SuitableFood
4. cow2 eat new cow1.SuitableFood // compilation error
Trên dòng 4 bạn sẽ thấy một lỗi vì Grass hiện là một lớp bên trong của Cow, do đó, để tạo một thể hiện của Grass, chúng ta cần một đối tượng bò và đối tượng bò này xác định đường dẫn. Vì vậy, 2 đối tượng bò cho ra 2 con đường khác nhau. Trong kịch bản này, cow2 chỉ muốn ăn thức ăn được tạo ra đặc biệt cho nó. Vì thế:
cow2 eat new cow2.SuitableFood
Bây giờ mọi người đều hạnh phúc :-)