Kiểu interface Kiểu interface giống như 1 lớp trừu tượng nhưng chỉ bao gồm tên các thành viên trừu tượng thuộc tính, phương thức Mọi thành viên trong interface đều là public không viế
Trang 1Giao diệnInterfaces
Trang 2Kiểu interface
Kiểu interface giống như 1 lớp trừu tượng nhưng chỉ bao gồm tên các thành viên trừu tượng (thuộc tính, phương thức)
Mọi thành viên trong interface đều là public (không viết khi định nghĩa thành viên)
Tên interface nên được bắt đầu bằng kí tự I hoapublic interface IPoint
{ double X { get; set; } double Y { get; set; } void Draw();
}
Trang 3Giao diện và lớp
Interface
Không thể tạo thể hiện bằng từ khóa new
Không thể định nghĩa trường
Các thành viên đều là public (nhưng không viết public)
Không có hàm khởi tạo
Không được hiện thực các phương thức
Khi hiện thực interface, bắt buộc phải hiện thực tất
cả phương thức, không sử dụng từ khóa override
Có thể tạo hàm khởi tạo
Phải hiện thực các phương thức (trừ lớp trừu tượng)
Khi kế thừa, không cần ghi đè các phương thức, nếu ghi đè phải có từ khóa override
Trang 4Hiện thực một giao diện
Trong C#, chúng ta có thể dùng class hoặc struct để hiện thực 1 giao diện, cú pháp giống như kế thừa 1 classpublic class Point : IPoint
C# cho phép 1 class hoặc struct hiện thực được nhiều giao diệnpublic class Point : IPoint, IComparable
Khi hiện thực 1 giao diện, ta phải hiện thực toàn bộ các phương thức của giao diện đó, kể cả các hàm get, set của thuộc tính
Trang 5Hiện thực một giao diện
public class Point : IPoint{
public double X { get; set; } public double Y { get; set; } public void Draw()
{ Console.WriteLine(“{0} {1}”, X, Y); }
public Point() { } public Point(double x, double y) {
X = x; Y = y;
}}
Trang 6Gọi các thành viên của
giao diện ở cấp độ đối
tượng
Ta có thể tạo 1 thể hiện của giao diện bằng cách ép kiểu tường minh 1 đối tượng Nếu đối tượng này thuộc kiểu class hiện thực giao diện thì chuyển đổi thành công (tạm gọi là tương thích với kiểu giao diện đó), ngược lại thì sẽ ném ra 1 ngoại lệ kiểu InvalidCastException
Ta có thể gọi các thành viên của giao diện thông qua thể hiện này, các thành viên của thể hiện này chính là các thành viên của đối tượng được ép kiểu
Point a = new Point(1, 2);
IPoint b = (IPoint)a;
b.Draw();
// Output:
// 1 2
Trang 7Ép kiểu thành giao diện
Tương tự ép kiểu với class, ta có thể dùng các toán tử ép kiểu, toán tử as để ép kiểu và toán tử is để kiểm tra tính tương thích
Point p1 = new Point(2,3);
Humans man = new Humans();
IPoint a = (IPoint)p1;
IPoint b = man as IPoint; // b = nullbool kt = p1 is IPoint; // kt = true
Trang 8Kiểu interface trong tham
số của phương thức
Trong 1 phương thức, ta có thể khai báo tham số có kiểu interface
Khi truyền giá trị cho hàm, ta có thể truyền bất kì đối tượng nào có kiểu tương thích với interface đó, việc chuyển kiểu sẽ được làm tụ động
public static void Draw3D(IPoint p)
{ Console.WriteLine(“Draw 3D: {0} {1}”, p.X, p.Y);
}
Trang 9Kiểu interface trong tham
số của phương thức
public static void Main(string[] args)
{ Point p1 = new Point(1, 2);
IPoint ip = (IPoint) new Point(3, 4); Draw3D(p1);
Draw3D(ip);
}// Output:
// Draw 3D: 1 2// Draw 3D: 3 4
Trang 10Kiểu interface là kiểu trả về
của phương thức
Tương tự với tham số kiểu interface, ta có thể return bất kì đối tượng nào tương thích với kiểu interface đópublic IPoint Add(IPoint a, IPoint b)
{ return new Point(a.X + b.X, a.Y + b.Y);
// hoặc có thể return thể hiện của IPoint // return (IPoint) new Point(a.X + b.X, a.Y + b.Y);
}
Trang 11Mảng kiểu giao diện
Ta có thể tạo mảng có kiểu là giao diện, các phần tử của mảng là các đối tượng tương thích với kiểu giao diện đóIPoint[] arr = {
new Point(), new Point(1,2), (IPoint) new Point(2,1),};
Trang 12Hiện thực giao diện tường
minh
Ở bên trên, ta đã hiện thực giao diện IPoint bằng class Point theo cách không tường minh Việc hiện thực không tường minh này có thể dẫn tới trường hợp nhiều interface có chung 1 phương thức Cách giải quyết là hiện thực giao diện tường minh
public interface IDrawToForm{
void Draw();
}public interface IDrawToMemory{
void Draw();
}public interface IDrawToPrinter{
void Draw();
}
Trang 13Hiện thực giao diện tường
minh
public class Rectangle : IDrawToForm, IDrawToMemory, IDrawToPrinter
{ void IDrawToForm.Draw() { }
void IDrawToMemory.Draw() { }
void IDrawToPrinter.Draw() { }
}
Khi hiện thực theo cách này, các thành viên đều là private, ta không thể thêm các bổ từ truy xuất, để gọi các thành viên này, ta cần tạo 1 thể hiện của giao diện rồi gọi bằng thế hiện đó
Trang 14Hiện thực giao diện tường
}
Trang 15 Nếu mở rộng nhiều giao diện, có thể xảy ra trùng tên thành viên, khi hiện thực giao diện mở rộng, ta có thể hiện thực từng thành viên trùng tên bằng cách hiện thực tường minh
Trang 16double Z { get; set; }}
public class Point3D : IPoint3D{
double IPoint.X { get; set; } double IPoint.Y { get; set; } double IPoint3D.Z { get; set; } void IPoint.Draw() { }
void IDrawable.Draw() { }}
Trang 17Một vài
giao diện quen thuộc
Trang 18 Hàm GetEnumerator trả về 1 kiểu IEnumeratorpublic interface IEnumerator
{ bool MoveNext();
object Current { get; } void Reset();
}
Trang 19Lệnh foreach
Giả sử có class Cars hiện thực giao diện IEnumerable, đối tượng cars có kiểu Cars, câu lệnh foreach có dạngforeach(Car a in cars)
{ // Lệnh}
Tương đương vớiIEnumerator list = ((IEnumerable)cars).GetEnumerator();
list.Reset();
while (list.MoveNext()){
Car a = (Car)list.Current;
// Lệnh}
Trang 20Phương thức trả về nhiều
lần với từ khóa yield
Để sử dụng phương thức trả về nhiều lần, phương thức đo phải trả về một IEnumerable
Với từ khóa yield return, phương thức sẽ trả về 1 giá trị trong danh sách các phần tử của IEnumerable rồi tiếp tục chạy phương thức cho đến khi hết các lệnh hoặc đến khi gặp yield break
public IEnumerator F()
{ yield return 1;
yield return 2;
yield return 3;
}
Trang 21for(int i=0; i<n; i++) {
yield return a.Next();
}}
Trang 22 ICloneable: để sao chép 1 đối tượng từ 1 đối tượng khác bằng phương thức Clonepublic interface ICloneable
{ object Clone();
Trang 23 IComparable: dùng để so sánh 2 đối tượng cùng kiểu với phương thức CompareTopublic interface IComparable
{ int CompareTo(object obj);
}
Khi 1 class hiện thực giao diện này, mảng các phần tử kiểu class đó sẽ dùng được phương thức Sort (sắp xếp)
Sử dụngCar[] arr = { };
Array.Sort(arr);
Trang 24 IComparer: dùng để so sánh 2 đối tượng, được sử dụng để sắp xếp mảng theo thứ tự tùy ýpublic interface IComparer
{ int Compare(object obj1, object obj2)}
Sử dụngIComparer a = ;
Car[] arr = { };
Array.Sort(arr, a);