Trong việc thực thi giao diện cho tới giờ, những lớp thực thi (trong trường hợp này là
Document) tạo ra các phương thức thành viên cùng ký hiệu và kiểu trả về như là phương thức được mô tả trong giao diên. Chúng ta không cần thiết khai báo tường minh rằng đây là một thực thi của một giao diện, việc này được hiểu ngầm bởi trình biên dịch.
Tuy nhiên, có vấn đề xảy ra khi một lớp thực thi hai giao diện và cả hai giao diện này có các phương thức cùng một ký hiệu. Ví dụ 8.5 tạo ra hai giao diện: IStorable và ITalk. Sau đó thực thi phương thức Read() trong giao diện ITalk để đọc ra tiếng nội dung của một cuốn sách. Không may là phương thức này sẽ tranh chấp với phương thức Read() của IStorable mà
Document phải thực thi.
Bởi vì cả hai phương thức IStorable và ITalk có cùng phương thức Read(),việc thực thi lớp
Document phải sử dụng thực thi tường minh cho mỗi phương thức. Với việc thực thi tường minh, lớp thực thi Document sẽ khai báo tường minh cho mỗi phương thức:
void ITalk.Read();
Điều này sẽ giải quyết việc tranh chấp, nhưng nó sẽ tạo ra hàng loạt các hiệu ứng thú vị. Đầu tiên, không cần thiết sử dụng thực thi tường minh với những phương thức khác của Talk:
public void Talk();
vì không có sự tranh chấp cho nên ta khai báo như thông thường.
Điều quan trọng là các phương thức thực thi tường minh không có bổ sung truy cập:
void ITalk.Read();
Thật vậy, một phương thức được khai báo tường minh thì sẽ không được khai báo với các từ khóa bổ sung truy cập: abstract, virtual, override, và new.
Một địều quan trọng khác là chúng ta không thể truy cập phương thức thực thi tường minh thông qua chính đối tượng. Khi chúng ta viết:
theDoc.Read();
Trình biên dịch chỉ hiểu rằng chúng ta thực thi phương thức giao diện ngầm định cho
IStorable. Chỉ một cách duy nhất truy cập các phương thức thực thi tường minh là thông qua việc gán cho giao diện để thực thi:
ITalk itDoc = theDoc as ITalk; if ( itDoc != null )
{
itDoc.Read(); }
Sử dụng thực thi tường minh được áp dụng trong ví dụ 8.5
Ví dụ 8.5: Thực thi tường minh.
--- using System; interface IStorable { void Read(); void Write(); } interface ITalk { void Talk(); void Read(); }
// lớp Document thực thi hai giao diện public class Document : IStorable, ITalk {
// bộ khởi dựng
public Document( string s) {
Console.WriteLine(“Creating document with: {0}”,s); }
// tạo phương thức ảo public virtual void Read() {
Console.WriteLine(“Implementing IStorable.Read”); }
// thực thi bình thường public void Write() {
Console.WriteLine(“Implementing IStorable.Write”); }
// thực thi tường minh void ITalk.Read() {
Console.WriteLine(“Implementing ITalk.Read”); }
public void Talk() {
Console.WriteLine(“Implementing ITalk.Talk”); }
}
public class Tester {
static void Main() {
// tạo đối tượng Document
Document theDoc = new Document(“Test Document”); IStorable isDoc = theDoc as IStorable;
if ( isDoc != null ) {
isDoc.Read(); }
ITalk itDoc = theDoc as ITalk; if ( itDoc != null ) { itDoc.Read(); } theDoc.Read(); theDoc.Talk(); } } ---
Kết quả:
Creating document with: Test Document Implementing IStorable.Read
Implementing ITalk.Read Implementing IStorable.Read Implementing ITalk.Talk
---
Lựa chọn việc thể hiện phương thức giao diện
Những người thiết kế lớp có thể thu được lợi khi một giao diện được thực thi thông qua thực thi tường minh và không cho phép các thành phần client của lớp truy cập trừ phi sử dụng thông qua việc gán cho giao diện.
Giả sử nghĩa của đối tượng Document chỉ ra rằng nó thực thi giao diện IStorable, nhưng không muốn phương thức Read() và Write() là phần giao diện public của lớp
Document. Chúng ta có thể sử dụng thực thi tường minh để chắc chắn chỉ có thể truy cập thông qua việc gán cho giao diện. Điều này cho phép chúng ta lưu trữ ngữ nghĩa của lớp
Document trong khi vẫn có thể thực thi được giao diện IStorable. Nếu thành phần client muốn đối tượng thực thi giao diện IStorable, nó có thể thực hiện gán tường minh cho giao diện để gọi các phương thức thực thi giao diện. Nhưng khi sử dụng đối tượng Document thì nghĩa là không có phương thức Read() và Write().
Thật vậy, chúng ta có thể lựa chọn thể hiện những phương thức thông qua thực thi tường minh, do đó chúng ta có thể trưng bày một vài phương thức thực thi như là một phần của lớp Document và một số phương thức khác thì không. Trong ví dụ 8.5, đối tượng
Document trưng bày phương thức Talk() như là phương thức của lớp Document, nhưng phương thức Talk.Read() chỉ được thể hiện thông qua gán cho giao diện. Thậm chí nếu
IStorable không có phương thức Read(), chúng ta cũng có thể chọn thực thi tường minh phương thức Read() để phương thức không được thể hiện ra bên ngoài như các phương thức của Document.
Chúng ta lưu ý rằng vì thực thi giao diện tường minh ngăn ngừa việc sử dụng từ khóa
virtual, một lớp dẫn xuất có thể được hỗ trợ để thực thi lại phương thức. Do đó, nếu Note
dẫn xuất từ Document, nó có thể được thực thi lại phương thức Talk.Read() bởi vì lớp
Document thực thi phương thức Talk.Read() không phải ảo.
Ẩ n thành viên
Ngôn ngữ C# cho phép ẩn các thành viên của giao diện. Ví dụ, chúng ta có một giao diện
IBase với một thuộc tính P: