21.2.1. Thực thi giao diện
Khi xây dựng một lớp ta có thể kế thừa từ một lớp cơ sở và thực thi một hoặc nhiều giao diện. Để thực thi giao diện ta đặt giao diện sau dấu : sau phần khai báo tên lớp, nếu lớp kế thừa một lớp cơ sở và thực thi nhiều giao diện thì lớp cơ sở dứng trước các giao diện, lớp cơ sở và giao diện ngăn cách nhau bởi dấu phẩy (,). Khi một lớp thực thi một giao diện thì lớp đó phải thực thi tất cả các thuộc tính và phương thức khai báo trong giao diện. Nếu không thực thi hết thì chương trình dịch sẽ báo lỗi
Ví dụ 4.1 (tiếp) thực thi giao diện
using System;
namespace LTHDTC {
class Diem {
protected int x,y;
public Diem (int x, int y) { this.x=x; this.y=y; } public int X { get { return x; } set
{ x = value; } } public int Y { get { return y; } set { y = value; } } } interface IHinh { string TenHinh { get; } double ChuVi(); double DienTich(); void InThongTin(); } class HinhTron:IHinh { Diem tam; double bankinh;
public HinhTron(int x, int y, double bankinh) {
this.bankinh = bankinh; }
public string TenHinh {
get { return "Hinh Tron"; } }
public double ChuVi() {
return Math.PI * bankinh * 2; }
public double DienTich() {
return Math.PI * bankinh * bankinh; }
public void InThongTin() {
Console.WriteLine("{0} co dien tich la: {1}; chu vi la: {2}", TenHinh, DienTich(), ChuVi());
} } }
Truy cập phương thức giao diện
Chúng ta có thể truy cập những thành viên của giao diện IHinh như thể là các thành viên của lớp HinhTron
HinhTron h = new HinhTron(4, 7, 4); h. InThongTin();
hay là ta có thể tạo thể hiện của giao diện bằng cách gán đối tượng HinhTron cho một kiểu dữ liệu giao diện, và sau đó sử dụng giao diện này để truy cập các phương thức:
HinhTron h = new HinhTron(4, 7, 4); IHinh hinh = (IHinh)h;
Hinh. InThongTin();
chúng ta không thể thực hiện như sau:
Ihinh hinh=new IHinh();
Tuy nhiên chúng ta có thể tạo thể hiện của lớp thực thi giao diện như sau:
HinhTron h = new HinhTron(4, 7, 4);
Sau đó chúng ta có thể tạo thể hiện của giao diện bằng cách gán đối tượng thực thi đến kiểu dữ liệu giao diện, trong trường hợp này là IHinh
IHinh hinh= (IHinh) h;
Chúng ta có thể kết hợp những bước trên như sau:
IHinh hinh= (IHinh) new HinhTron(4, 7, 4);
Nói chung, cách thiết kế tốt nhất là quyết định truy cập những phương thức của giao diện thông qua tham chiếu của giao diện. Do vậy cách tốt nhất là sử dụng hinh.InThongTin() hơn là sử dụng h.InThongTin() trong ví dụ trước. Truy cập thông qua giao diện cho phép chúng ta đối xử giao diện một cách đa hình. Nói cách khác, chúng ta tạo hai hay nhiều hơn những lớp thực thi giao diện, và sau đó bằng cách truy cập lớp này chỉ thông qua giao diện.
Gán đối tượng cho một giao diện
Trong nhiều trường hợp, chúng ta không biết trước một đối tượng có hỗ trợ một giao diện đưa ra. Giả sử ta viết thêm một giao diện Ithu nào đó nhưng lớp HinhTron của chúng ta không triển khai giao diện này thì phéo gán sau sẽ không hợp lệ
Ithu t=(IThu)h;
Khi biên dịch chương trình thì dòng lệnh trên không hề bị báo lỗi vì Ithu là một giao diện hoàn toàn hợp lệ, Tuy nhiên khi chạy chương trình sẽ tạo ra một ngoại lệ (exception). Và chương trình dừng lại.
Giao diện đối lập với lớp trừu tượng
Giao diện rất giống như các lớp trừu tượng. Thật vậy, chúng ta có thể thay thế khai báo của IHinh trở thành một lớp trừu tượng:
abstract class IHinh
abstract public void ChuVi();
abstract public void DienTich();
}
Bây giờ lớp HinhChuNhat có thể thừa kế từ lớp trừu tượng IHinht, và cũng không có gì khác nhiều so với việc sử dụng giao diện.
Tuy nhiên, giả sử chúng ta mua một lớp ClsDaGiac từ một hãng thứ ba và chúng ta muốn kết hợp với lớp có sẵn như IHinh. Tuy nhiên trong ngôn ngữ C# chúng ta không cho phép thực hiện đa kế thừa.
Tuy nhiên, ngôn ngữ C# cho phép chúng ta thực thi bất cứ những giao diện nào và dẫn xuất từ một lớp cơ sở. Do đó, bằng cách làm cho IHinh là một giao diện, chúng ta có thể kế thừa từ lớp ClsDaGiac và cũng từ giao diện IHinh. Ta có thể tạo lớp HinhChuNhat như sau:
public class HinhChuNhat: ClsDaGiac, IHinh
{
// Code của lớp
}