Tải bản đầy đủ (.pptx) (24 trang)

Interface trong C#

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (92 KB, 24 trang )

Giao diện
Interfaces
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ết khi định nghĩa thành viên)

Tên interface nên được bắt đầu bằng kí tự I hoa
public interface IPoint
{
double X { get; set; }
double Y { get; set; }
void Draw();
}
Giao 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
Class

Có thể tạo thể hiện bằng new (trừ lớp trừu
tượng)

Có trường dữ liệu

Các thành viên có thể là public, private,
protected

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
Hiệ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 class
public class Point : IPoint

C# cho phép 1 class hoặc struct hiện thực được nhiều giao diện
public 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
Hiệ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;
}
}
Gọ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
É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 = null
bool kt = p1 is IPoint; // kt = true
Kiể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);
}
Kiể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

Kiể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);
}
Mả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),
};
Hiệ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();
}
Hiệ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 đó
Hiện thực giao diện tường
minh

Trong cùng 1 class hiện thực nhiều giao diện, ta có thể hiện thực theo kiểu tường minh và không tường minh. Các
giao diện không được hiện thực tường minh thì sẽ nhận giá trị hiện thực không tường minh
public class Triangle : IDrawToForm, IDrawToMemory, IDrawToPrinter
{
public void Draw()
{ }
void IDrawToPrinter.Draw()

{ }
}
Mở rộng giao diện

Ta có thể mở rộng 1 giao diện để thêm vào các thuộc tính và phương thức, mở rộng giao diện giống như kế thừa
class
public interface IPoint3D : IPoint
{
double Z { get; set; }
}

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
Mở rộng giao diện (Ví dụ)
public interface IDrawable
{
void Draw();
}
public interface IPoint3D : IPoint, IDrawable
{
double 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() { }
}

Một vài
giao diện quen thuộc
IEnumerable &
IEnumerator

IEnumerable: dùng để liệt kê các phần tử của 1 đối tượng thông qua lệnh foreach
public interface IEnumerable
{
IEnumerator GetEnumerator();
}

Hàm GetEnumerator trả về 1 kiểu IEnumerator
public interface IEnumerator
{
bool MoveNext();
object Current { get; }
void Reset();
}
Lệ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ạng
foreach(Car a in cars)
{
// Lệnh
}

Tương đương với
IEnumerator list = ((IEnumerable)cars).GetEnumerator();
list.Reset();
while (list.MoveNext())

{
Car a = (Car)list.Current;
// Lệnh
}
Phươ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;
}
Từ khóa yield
(ví dụ)

Ví dụ hàm Generator trả về 1 kiểu IEnumerable gồm n số ngẫu nhiên
public IEnumerable Generator(int n)
{
Random a = new Random();
for(int i=0; i<n; i++)
{
yield return a.Next();
}
}
ICloneable


ICloneable: để sao chép 1 đối tượng từ 1 đối tượng khác bằng phương thức Clone
public interface ICloneable
{
object Clone();
}

Khi hiện thực giao diện này, trong phương thức Clone, ta nên sử dụng phương thức MemberwiseClone của lớp
Object

Sử dụng:
Car a = new Car();
Car b = (Car)a.Clone();
IComparable

IComparable: dùng để so sánh 2 đối tượng cùng kiểu với phương thức CompareTo
public 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ụng
Car[] arr = { };
Array.Sort(arr);
IComparer

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ụng
IComparer a = ;
Car[] arr = { };
Array.Sort(arr, a);

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×