Giới thiệu interface
Giới thiệu interface
Một interface hơi giống một lớp mà không cần triển khai. Nó chỉ định một tập hợp các đặc điểm và hành vi bằng cách xác định chữ ký cho các phương thức, thuộc tính, sự kiện và bộ chỉ mục, mà không chỉ định cách thức bất kỳ thành viên nào trong số này được thực hiện. Khi một lớp thực hiện một interface, lớp sẽ cung cấp một triển khai cho từng thành viên của interface. Bằng cách thực hiện interface, lớp sẽ đảm bảo rằng nó sẽ cung cấp các chức năng được chỉ định bởi interface.
Lưu ý phân biệt quan trọng khi sử dụng Interface. Một lớp "thực hiện" một interface trái ngược với "kế thừa" một lớp cơ sở.
Tạo interface
Tạo interface
Bạn có thể nghĩ về một interface như một hợp đồng. Bằng cách triển khai một interface cụ thể, một lớp đảm bảo cho người dùng rằng nó sẽ cung cấp chức năng cụ thể thông qua các thành viên cụ thể, mặc dù việc triển khai thực tế không phải là một phần của hợp đồng.
Cú pháp để xác định một interface tương tự như cú pháp để xác định một lớp. Bạn sử dụng từ khóa interface để khai báo một interface, như ví dụ sau:
// Declaring an Interface
public interface IBeverage
{
// Methods, properties, events, and indexers go here.
}
Lưu ý: Quy ước lập trình (Programming Convention) chỉ ra rằng tất cả các tên interface nên bắt đầu bằng "I".
Tương tự như một khai báo lớp, một khai báo interface có thể bao gồm một access modifiers. Bạn có thể sử dụng các access modifiers sau trong khai báo interface của mình:
Access modifier
|
Sự miêu tả
|
Public
|
The interface có khả năng chạy trong bất kỳ assembly nào.
|
Internal
|
Interface có khả thể chạy trong cùng một assembly, nhưng không thể chạy trong một assembly khác. Đây là giá trị mặc định nếu bạn không chỉ định access modifiers.
|
Adding Interface Members
Một interface xác định chữ ký của các thành viên nhưng không bao gồm bất kỳ chi tiết thực hiện. Các interface có thể bao gồm các phương thức, thuộc tính, sự kiện và bộ chỉ mục:
- Để xác định một phương thức, bạn chỉ định tên của phương thức, kiểu trả về và bất kỳ tham số nào:
int GetServingTemperature(bool includesMilk);
- Để xác định một thuộc tính, bạn chỉ định tên của thuộc tính, thuộc tính và property accessors:
bool IsFairTrade { get; set; }
- Để xác định một sự kiện, bạn sử dụng từ khóa sự kiện, theo sau là đại biểu xử lý sự kiện, theo sau là tên của sự kiện:
event EventHandler OnSoldOut;
- Để xác định một bộ chỉ mục, bạn chỉ định loại trả về và access modifiers:
string this[int index] { get; set; }
Thành viên interface không bao gồm access modifiers. Mục đích của interface là xác định các thành viên mà một lớp triển khai nên hiển thị cho người dùng, để tất cả các thành viên interface được công khai. Các interface không thể bao gồm các thành viên liên quan đến chức năng bên trong của một lớp, chẳng hạn như các trường, hằng, toán tử và constructor.
Hãy xem một ví dụ cụ thể. Giả sử rằng bạn muốn phát triển chương trình thẻ khách hàng thân thiết cho một ứng dụng liên quan đến một công ty cà phê. Bạn có thể bắt đầu bằng cách tạo interface có tên ILoyaltyCardHolder xác định:
- Một thuộc tính số nguyên chỉ đọc có tên TotalPoints.
- Một phương thức có tên AddPoints chấp nhận đối số thập phân.
- Một phương thức có tên ResetPoints.
Ví dụ sau đây cho thấy một interface xác định một thuộc tính chỉ đọc và hai phương thức:
// Defining an Interface
public interface ILoyaltyCardHolder
{
int TotalPoints { get; }
int AddPoints(decimal transactionValue);
void ResetPoints();
}
Lưu ý rằng các phương thức trong interface không bao gồm các phần thân phương thức. Tương tự, các thuộc tính trong interface cho biết những access modifiers nào được đưa vào nhưng không cung cấp bất kỳ chi tiết triển khai nào. Interface chỉ đơn giản nói rằng bất kỳ lớp thực hiện nào cũng phải bao gồm và cung cấp một triển khai cho ba thành viên. Người tạo ra lớp triển khai có thể chọn cách các phương thức được thực hiện. Ví dụ: bất kỳ triển khai phương thức AddPoints nào cũng sẽ chấp nhận đối số thập phân (giá trị tiền mặt của giao dịch khách hàng) và trả về một số nguyên (số điểm được thêm vào). Nhà phát triển lớp có thể thực hiện phương thức này theo nhiều cách khác nhau. Ví dụ: việc triển khai phương thức AddPoints có thể:
- Tính số điểm cần thêm bằng cách nhân giá trị giao dịch với một số tiền cố định.
- Lấy số điểm cần thêm bằng cách gọi một dịch vụ.
- Tính số điểm cần thêm bằng cách sử dụng các yếu tố bổ sung, chẳng hạn như vị trí của chủ thẻ khách hàng thân thiết.
Ví dụ sau đây cho thấy một lớp thực hiện interface ILoyaltyCardHolder:
// Implementing an Interface
public class Customer : ILoyaltyCardHolder
{
private int totalPoints;
public int TotalPoints
{
get { return totalPoints; }
}
public int AddPoints(decimal transactionValue)
{
int points = Decimal.ToInt32(transactionValue);
totalPoints += points;
return totalPoints;
}
public void ResetPoints()
{
totalPoints = 0;
}
// Other members of the Customer class.
}
Các chi tiết của việc thực hiện không quan trọng đối với việc gọi các lớp. Bằng cách triển khai interface ILoyaltyCardHolder, lớp triển khai sẽ cho người dùng biết rằng họ sẽ chăm sóc hoạt động AddPoints. Một trong những lợi thế chính của interface là chúng cho phép bạn mô đun hóa mã của mình. Bạn có thể thay đổi cách thức lớp của bạn thực hiện interface tại bất kỳ thời điểm nào mà không phải cập nhật bất kỳ lớp người dùng nào dựa vào việc triển khai interface.
Implicit and Explicit Implementation
Khi bạn tạo một lớp thực hiện một interface, bạn có thể chọn thực hiện interface ngầm hay rõ ràng. Để thực hiện một interface ngầm, bạn triển khai từng thành viên interface bằng một chữ ký phù hợp với định nghĩa thành viên trong interface. Để thực hiện một interface rõ ràng, bạn hoàn toàn đủ điều kiện cho mỗi tên thành viên để rõ ràng rằng thành viên đó thuộc về một interface cụ thể.
Ví dụ sau đây cho thấy việc triển khai rõ ràng interface IBeverage:
// Implementing an Interface Explicitly
public class Coffee : IBeverage
{
private int servingTempWithoutMilk { get; set; }
private int servingTempWithMilk { get; set; }
public int IBeverage.GetServingTemperature(bool includesMilk)
{
if(includesMilk)
{
return servingTempWithMilk;
}
else
{
return servingTempWithoutMilk;
}
}
public bool IBeverage.IsFairTrade { get; set; }
// Other non-interface members.
}
Trong hầu hết các trường hợp, cho dù bạn thực hiện một interface ngầm hay rõ ràng là một lựa chọn thẩm mỹ. Nó không tạo ra sự khác biệt trong cách lớp của bạn biên dịch. Một số nhà phát triển thích triển khai interface rõ ràng vì làm như vậy có thể làm cho mã dễ hiểu hơn. Kịch bản duy nhất mà bạn phải sử dụng triển khai interface rõ ràng là nếu bạn đang triển khai hai interface chia sẻ tên thành viên. Ví dụ: nếu bạn triển khai các interface có tên IBeverage và IInventoryItem và cả hai interface đều khai báo thuộc tính Boolean có tên IsAvailable, bạn sẽ cần phải thực hiện rõ ràng ít nhất một trong số các thành viên IsAvailable. Trong trường hợp này, trình biên dịch sẽ không thể giải quyết tham chiếu IsAvailable mà không có triển khai rõ ràng
Interface Polymorphism
Interface Polymorphis
Vì nó liên quan đến các interface, tính đa hình nói rằng bạn có thể biểu diễn một thể hiện của một lớp như là một thể hiện của bất kỳ interface nào mà lớp thực hiện. Đa hình interface có thể giúp tăng tính linh hoạt và tính mô đun của mã của bạn. Giả sử bạn có một số lớp thực hiện interface IBeverage, chẳng hạn như Coffee, Tea, Juice v.v. Bạn có thể viết mã làm việc với bất kỳ lớp nào trong số này dưới dạng các trường hợp của IBeverage mà không cần biết bất kỳ chi tiết nào về lớp triển khai. Ví dụ, bạn có thể tạo một tập hợp các trường hợp IBeverage mà không cần biết chi tiết của mỗi lớp thực hiện IBeverage.
Ví dụ: nếu lớp Coffee thực hiện interface IBeverage, bạn có thể biểu diễn một đối tượng Coffee mới như một thể hiện của Coffee hoặc một thể hiện của IBeverage:
// Representing an Object as an Interface Type
Coffee coffee1 = new Coffee();
IBeverage coffee2 = new Coffee();
Bạn có thể sử dụng một assembly từ ẩn để chuyển đổi thành một loại interface, bởi vì bạn biết rằng lớp phải bao gồm tất cả các thành viên interface.
// Casting to an Interface Type
IBeverage beverage = coffee1;
Bạn phải sử dụng ép kiểu rõ ràng để chuyển đổi từ loại interface sang loại lớp dẫn xuất, vì lớp có thể bao gồm các thành viên không được xác định trong interface.
// Casting an Interface Type to a Derived Class Type
Coffee coffee3 = beverage as Coffee;
// OR
Coffee coffee4 = (Coffee)beverage;
Implementing Multiple Interfaces
Trong nhiều trường hợp, bạn sẽ muốn tạo các lớp thực hiện nhiều interface. Ví dụ: bạn có thể muốn:
- Triển khai interface IDisposable để cho phép thời gian chạy .NET xử lý lớp của bạn một cách chính xác.
- Triển khai interface IComparable để cho phép các lớp tập hợp sắp xếp các thể hiện của lớp của bạn.
- Thực hiện interface tùy chỉnh của riêng bạn để xác định chức năng của lớp.
Để thực hiện nhiều interface, bạn thêm một danh sách các interface được phân tách bằng dấu phẩy mà bạn muốn triển khai vào khai báo lớp. class của bạn phải thực hiện mọi thành viên của mọi interface bạn thêm vào khai báo lớp. Ví dụ sau đây cho thấy cách tạo một lớp thực hiện nhiều interface:
// Declaring a Class that Implements Multiple Interfaces
public class Coffee: IBeverage, IInventoryItem
{
}
Đăng nhận xét