Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 13 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
13
Dung lượng
182,76 KB
Nội dung
Thựcthigiaodiện tường minh Trong việc thựcthigiaodiện cho tới giờ, những lớp thựcthi (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ựcthi 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 giaodiện và cả hai giaodiệ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ựcthi phương thức Read() trong giaodiệ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ựcthi lớp Document phải sử dụng thựcthi tường minh cho mỗi phươ ng thức. Với việc thựcthi tường minh, lớp thựcthi 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ựcthi 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ựcthi tường minh không có bổ sung truy cập: void ITalk.Read(); Phương thức này được hiểu ngầm là public. 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ứcthựcthi 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ựcthi phương thứcgiao di ện ngầm định cho IStorable. Chỉ một cách duy nhất truy cập các phương thứcthựcthi tường minh là thông qua việc gán cho giaodiện để thực thi: ITalk itDoc = theDoc as ITalk; if ( itDoc != null ) { itDoc.Read(); } Sử dụng thựcthi tường minh được áp dụng trong ví dụ 8.5 Ví dụ 8.5: Thựcthi tường minh. ----------------------------------------------------------------------------- using System; interface IStorable { void Read(); void Write(); } interface ITalk { void Talk(); void Read(); } // lớp Document thựcthi hai giaodiệ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ựcthi bình thường public void Write() { Console.WriteLine(“Implementing IStorable.Write”); } // thựcthi 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ứcgiaodiện Những người thiết kế lớp có thể thu được lợi khi một giaodiện được thựcthi thông qua thựcthi 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ựcthigiaodiện IStorable, nhưng không muốn phương thức Read() và Write() là phần giaodiện public của lớp Document. Chúng ta có thể sử dụng thựcthi 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ựcthi được giaodiện IStorable. Nếu thành phần client muốn đối tượng thực thigiaodiện IStorable, nó có thể thực hiệ n gán tường minh cho giaodiện để gọi các phương thức thực thigiao 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ựcthi tường minh, do đó chúng ta có thể trưng bày một vài phương thứcthựcthi 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ựcthi 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 thigiaodiệ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ựcthi lại phương thức. Do đó, nếu Note dẫn xuất từ Document, nó có thể được thựcthi lại phương thức Talk.Read() bởi vì lớp Document thựcthi 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 giaodiện IBase với một thuộc tính P: interface IBase { int P { get; set;} } và sau đó chúng ta dẫn xuất từ giaodiện này ra một giaodiện khác, IDerived, giaodiện mới này làm ẩn thuộc tính P với một phương thức mới P(): interface IDerived : IBase { new int P(); } Việc cài đặt này là một ý tưởng tốt, bây giờ chúng ta có thể ẩn thuộc tính P trong lớp cơ sở. Một thựcthi của giaodiện dẫn xuất này đòi hỏi tối thiểu một thành viên giaodiện tường minh. Chúng ta có thể sử dụng thựcthi tường minh cho thuộc tính của lớp cơ sở hoặc của phương thức dẫn xuất, hoặc chúng ta có thể sử dụng thựcthi tường minh cho c ả hai. Do đó, ba phiên bản được viết sau đều hợp lệ: class myClass : IDerived { // thựcthi tường minh cho thuộc tính cơ sở int IBase.p { get{ .}} // thựcthi ngầm định phương thức dẫn xuất public int P() { .} } class myClass : IDerived { // thựcthi ngầm định cho thuộc tính cơ sở public int P { get{ .}} // thựcthi tường minh phương thức dẫn xuất int IDerived.P() { .} } class myClass : IDerived { // thựcthi tường minh cho thuộc tính cơ sở int IBase.P { get{ .}} // thựcthi tường minh phương thức dẫn xuất int IDerived.P(){ .} } Truy cập lớp không cho dẫn xuất và kiểu giá trị Nói chung, việc truy cập những phương thức của một giaodiện thông qua việc gán cho giaodiệnthì thường được thích hơn. Ngoại trừ đối với kiểu giá trị (như cấu trúc) hoặc với các lớp không cho dẫn xuất (sealed class). Trong trường hợp này, cách ưu chuộng hơn là gọi phương thứcgiaodiện thông qua đối tượng. Khi chúng ta thựcthi một giaodiện trong một cấu trúc, là chúng ta đang thựcthi nó trong một kiểu d ữ liệu giá trị. Khi chúng ta gán cho môt tham chiếu giao diện, có một boxing ngầm định của đối tượng. Chẳng may khi chúng ta sử dụng giaodiện để bổ sung đối tượng, nó là một đối tượng đã boxing, không phải là đối tượng nguyên thủy cần được bổ sung. Xa hơn nữa, nếu chúng ta thay đổi kiểu dữ liệu giá trị, thì kiểu dữ liệu được boxing vẫn không thay đổi. Ví dụ 8.6 tạo ra một cấu trúc và thựcthi một giaodiện IStorable và minh họa việc boxing ngầm định khi gán một cấu trúc cho một tham chiếu giao diện. Ví dụ 8.6: Tham chiếu đến kiểu dữ liệu giá trị. ----------------------------------------------------------------------------- using System; // khai báo một giaodiện đơn interface IStorable { void Read(); int Status { get; set;} } // thựcthi thông qua cấu trúc public struct myStruct : IStorable { public void Read() { Console.WriteLine(“Implementing IStorable.Read”); } public int Status { get { } set { } } retur n statu s; status = value; [...]... theStruct.Status = 2; Console.WriteLine(“Changed object”); Console.WriteLine(“theStruct.Status: {0}”, theStruct.Status); // gán cho giao diện // boxing ngầm định IStorable isTemp = (IStorable) theStruct; // thi t lập giá trị thông qua tham chiếu giao diện isTemp.Status = 4; Console.WriteLine(“Changed interface”); Console.WriteLine(“theStruct.Status: {0}, isTemp: {1}”, theStruct.Status, isTemp.Status);... theStruct.Status, isTemp.Status); } } -Kết quả: theStruct.Status: -1 Changed object t h e S t ruct.Status: 2 Changed interface theStruct.Status: 2, isTemp: 4 Changed object theStruct.Status: 6, isTemp: 4 . 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. Thực thi giao diện tường minh 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)