Phạm vi truy xuất mặc định của mới phương thức ở interface là gì

Phạm vi truy xuất mặc định của mới phương thức ở interface là gì

 Ví dụ 1: Để dễ hình dung các bạn có thể liên tưởng đến con ếch, nó là loài lưỡng cư:

  • Vừa là động vật trên cạn.
  • Vừa là động vật có thể sống dưới nước.

Nên nó có thể “kế thừa” 2 lớp động vật này, nhưng trong C# chỉ hỗ trợ đơn thừa kế, mà không hỗ trợ đa thừa kế.

 Ví dụ 2: Cách đánh giá kết quả của sinh viên tại các trường đại học và các trung tâm như trung tâm tiếng Anh, trung tâm Tin học,… là khác nhau, chẳng hạn như đối với loại Giỏi thì:

  • Đối với trường đại học thì tổng điểm >= 3.6
  • Còn ở trung tâm tiếng Anh thì tổng điểm >= 85%

Rõ ràng ở đây, chúng ta thấy cùng một quy tắc xếp loại Giỏi nhưng cách tính và kết quả đưa ra là khác nhau. Thông qua 2 ví dụ này thì:

  • Làm thế nào để một lớp có thể sử dụng chung được các thuộc tính và phương thức của 2 hay nhiều lớp khác?
  • Làm thế nào để áp dụng các quy tắc khác nhau, tùy vào hoàn cảnh khác nhau của từng đối tượng?

=> Tất cả những điều này sẽ được giải quyết bằng cách sử dụng interface.2. Interface là gì? Và cú pháp khai báo

2. Interface là gì? Và cú pháp khai báo

#1. Interface là gì?

– Interface được hiểu là lớp nền (lớp base), tức là chỉ có nền móng thôi, tất cả mọi thứ còn lại là do chúng ta (các lập trình viên) tự xây dựng trên nền móng đó.

– Interface như là một lớp mặt nạ, như là một bản thiết kế cho các class cùng cách thức hoạt động, nhưng có thể cùng hoặc khác nhau về bản chất bên trong.

#2. Cú pháp khai báo interface
interface <: tên_base_interface> { // interface member }

Trong đó:

  •  : là public hoặc internal, nếu không ghi rõ mặc định là internal.
  • interface : từ khóa khai báo một interface.
  •  : thường bắt đầu bằng chữ I, ví dụ: IShape, IAnimal, IStudent,…
  • <: tên_base_interface> : trường hợp có implement từ interface khác thì dấu 2 chấm : biểu thị sự implement, tiếp theo sau là tên base interface.
// Khai báo interface IPeople interface IPeople { // interface member } // Khai báo interface IStudent, implement từ interface IPeople public interface IStudent : IPeople { // interface member }

3. Các đặc điểm của interface

 Một interface trông có vẻ giống như một class, nhưng nó chỉ mô tả prototype của các thành phần methods, properties, indexers và events mà không định nghĩa chúng. Các thành phần không được sử dụng trong interface là: constructor, destructor, field, hằng, thành phần static.

 Không thể khai báo hay chỉ định phạm vi truy cập (access modifiers) cho các thành phần bên trong interface. Các thành phần này sẽ mặc định là public.

■ Khai báo một interface IDung, bao gồm các thành phần ĐÚNG:

interface IDung { // method void xyz(); // property string name { get; set; } // indexer double this[int index] { get; set; } // event event EventHandler OnChanged; }

Khai báo một interface ISai, bao gồm các thành phần SAI:

interface ISai { // Không được sử dụng hàm [constructor] // error CS0526: Interfaces cannot contain constructors ISai() { } // Không được sử dụng hàm [destructor] // error CS0575: Only class types can contain destructors ~ISai() { } // Không được chỉ định phạm vi truy cập (access modifiers) // error CS0106: The modifier 'public' is not valid for this item public void xyz(); // error CS0106: The modifier 'protected' is not valid for this item protected void abc(); // Không được khai báo [field] // error CS0525: Interfaces cannot contain fields int number; // Không được khai báo hằng [const] // error CS0525: Interfaces cannot contain fields public const double PI = 3.14; // Không được định nghĩa hàm // error CS0531: 'ISai.xyz()': interface members cannot have a definition void xyz() { Console.WriteLine( "Print xyz" ); } // Không được sử dụng thành phần [static] // error CS0106: The modifier 'static' is not valid for this item static void xyz(); }

***Một interface sẽ được implement bởi các classes và structs, khi đó classes và structs bắt buộc phải định nghĩa tất cả các thành phần được mô tả trong interface.

■ Giả sử chúng ta có class Demo được implement từ interface IDung, thì bắt buộc class Demo phải định nghĩa tất cả các thành phần được khai báo trong interface IDung, kết quả như sau:

class Demo : IDung { // implement method public void xyz() { throw new NotImplementedException(); } // implement property public string name { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } // implement indexer public double this[int index] { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } // implement event public event EventHandler OnChanged; }

** Mỗi class hoặc struct có thể implement một hoặc nhiều interface, trường hợp nhiều interface thì sẽ được ngăn cách nhau bằng dấu phẩy.

// Ví dụ: class implement nhiều interface class ConEch : IDongVatTrenCan, IDongVatDuoiNuoc { // implement method interface IDongVatTrenCan public void Jump() { throw new NotImplementedException(); } // implement method interface IDongVatDuoiNuoc public void Swim() { throw new NotImplementedException(); } } interface IDongVatTrenCan { void Jump(); } interface IDongVatDuoiNuoc { void Swim(); }

** Mỗi interface không được phép kế thừa từ một class nào cả. Chỉ được phép implement từ một hoặc nhiều interface, trường hợp nhiều interface thì sẽ được ngăn cách nhau bằng dấu phẩy. Và khi implement từ base interface thì không thực hiện (không định nghĩa) các thành phần của base interface.

 ** Khác với class. Không thể tạo ra một đối tượng từ interface.

 ** Nếu một lớp implement từ nhiều interface có cùng tên thành viên thì trong lớp phải chỉ rõ thành viên đó thuộc interface nào (explicit interface). Xem demo ở Ví dụ 3 của mục 4.

4. Demo code minh họa cách sử dụng

 Ví dụ 1: Demo implement đơn interface. Chúng ta sẽ tạo ra một project UngDungLapTrinh để quy định cách xếp loại cho học viên gồm các file sau:

  • File IRank.cs : interface IRank đặt ra khuôn mẫu về cách xếp loại cho học viên.
  • File Apolo.cs : class implement interface IRank để định nghĩa quy tắc xếp loại cho trung tâm tiếng Anh.
  • File University.cs : class implement interface IRank để định nghĩa quy tắc xếp loại cho trường đại học.
  • File Program.cs : chứa hàm main() thực hiện chương trình.

■ Nội dung file IRank.cs

namespace UngDungLapTrinhh { interface IRank { // Khai báo prototype hàm xếp loại string Ranking(float score); }

■ Nội dung file Apolo.cs

namespace UngDungLapTrinh { // Implement interface IRank class Apolo : IRank { // Định nghĩa hàm Ranking // theo quy tắc xếp loại của trung tâm public string Ranking(float score) { if (score >= 85) { return "Distinction"; } if (score >= 65) { return "Credit"; } if (score >= 40) { return "Pass"; } return "Fail"; } } }
  • Nội dung file University.cs
namespace UngDungLapTrinh { // Implement interface IRank class University : IRank { // Định nghĩa hàm Ranking // theo quy tắc xếp loại của trường đại học public string Ranking(float score) { if (score >= 3.6) { return "Xuat sac"; } if (score >= 3.2) { return "Gioi"; } if (score >= 2.5) { return "Kha"; } if (score >= 2.0) { return "Trung Binh"; } return "Khong xep loai"; } } }

■ Nội dung file Program.cs

using System; namespace UngDungLapTrinh { class Program { static void Main(string[] args) { // Khai báo đối tượng của class Apolo apolo = new Apolo(); University university = new University(); // Gọi hàm xếp loại tương ứng với từng đối tượng Console.WriteLine("Apolo: " + apolo.Ranking(40)); Console.WriteLine("University: " + university.Ranking(2.6f)); Console.ReadKey(); } } }

Kết quả: Apolo: Pass

University: Kha

 Ví dụ 2: Demo implement đa interface. Chúng ta sẽ tạo ra một project MinhHoangBlog để mô tả tính lưỡng cư của con ếch gồm các file sau:

  • File ILandAnimal : interface ILandAnimal đặt ra khuôn mẫu về cách di chuyển của động vật trên cạn.
  • File IWaterAnimal.cs : interface IWaterAnimal đặt ra khuôn mẫu về cách di chuyển của động vật dưới nước.
  • File Frog.cs : class implement 2 interface ILandAnimal và IWaterAnimal để định nghĩa cách di chuyển ứng với khi trên mắt đất và lúc ở dưới nước.
  • File Program.cs : chứa hàm main() thực hiện chương trình.

■ Nội dung file ILandAnimal.cs

namespace UngDungLapTrinh { interface ILandAnimal { // Ếch: Di chuyển trên mặt đất là Nhảy void Jump(); } }

■ Nội dung file IWaterAnimal.cs

namespace UngDungLapTrinh { interface IWaterAnimal { // Ếch: Di chuyển dưới nước là Bơi void Swim(); } }

■ Nội dung file Frog.cs

using System; namespace UngDungLapTrinh { // Implement 2 interface class Frog : ILandAnimal, IWaterAnimal { // Định nghĩa method interface ILandAnimal public void Jump() { Console.WriteLine( "Frog jumps" ); } // Định nghĩa method interface IWaterAnimal public void Swim() { Console.WriteLine( "Frog swims" ); } } }

■ Nội dung file Program.cs

using System; namespace UngDungLapTrinh { class Program { static void Main(string[] args) { // Khởi tạo đối tượng lớp con Ếch Frog frog = new Frog(); // 2 cách di chuyển trên bờ và dưới nước frog.Jump(); frog.Swim(); Console.ReadKey(); } } }

Kết quả: Frog: jumps

Frog swims

 Ví dụ 3: Demo implement đa interface và trong các interface có method trùng tên. Chúng ta sẽ tạo ra một project UngDungLapTrinh để mô tả tính lưỡng cư của con ếch gồm các file sau:

  • File ILandAnimal : interface ILandAnimal khai báo prototype phương thức di chuyển Move().
  • File IWaterAnimal.cs : interface IWaterAnimal khai báo prototype phương thức di chuyển Move().
  • File Frog.cs : class implement 2 interface ILandAnimal và IWaterAnimal để định nghĩa cách di chuyển ứng với khi trên mắt đất và lúc ở dưới nước.
  • File Program.cs : chứa hàm main() thực hiện chương trình.

■ Nội dung file ILandAnimal.cs

namespace UngDungLapTrinh { interface ILandAnimal { void Move(); } }

■ Nội dung file IWaterAnimal.cs

namespace UngDungLapTrinh { interface IWaterAnimal { void Move(); } }


■ Nội dung file Frog.cs

– Lúc này, vì 2 interface ILandAnimal và IWaterAnimal có cùng tên phương thức là Move(), nên khi định nghĩa, chúng ta cần:

  1. Chỉ rõ phương thức Move() là của interface nào.
  2. Bỏ phạm vi truy cập là public đi.
public void Jump() → void ILandAnimal.Move() public void Swim() → void IWaterAnimal.Move() using System; namespace UngDungLapTrinh { // Implement 2 interface class Frog : ILandAnimal, IWaterAnimal { void ILandAnimal.Move() { Console.WriteLine( "Frog jumps" ); } void IWaterAnimal.Move() { Console.WriteLine( "Frog swims" ); } } }

■ Nội dung file Program.cs

– Vì 2 interface ILandAnimal và IWaterAnimal có cùng tên phương thức là Move(), nên khi gọi, chúng ta cần: chỉ rõ phương thức Move() là của interface nào, bằng cách dùng từ khóa as để cast về interface tương ứng.

using System; namespace UngDungLapTrinh { class Program { static void Main(string[] args) { // Khởi tạo đối tượng lớp con Ếch Frog frog = new Frog(); // Dùng từ khóa「as」để cast về interface tương ứng khi gọi hàm (frog as ILandAnimal).Move(); (frog as IWaterAnimal).Move(); Console.ReadKey(); } } }

Kết quả: Frog: jumps

Frog swims