Lập trình C#

Giới thiệu interface trong lập trình C#

Giới thiệu interface trong lập trình C#
Được viết bởi Minh Hoàng

Series lập trình C#, ngôn ngữ lập trình hiện đại và mạnh mẽ.

– Nội dung của bài viết này mình sẽ trình bày về interface trong C#. Đây là khái niệm rất cơ bản trong lập trình hướng đối tượng nói chung và lập trình C# nói riêng.

– Nếu bạn nào đã tìm hiểu và làm việc với ngôn ngữ lập trình Java thì khái niệm interface hoàn toàn không xa lạ. Vậy interface là gì? Mục đích sử dụng của nó? Chúng ta sẽ cùng nhau tìm hiểu theo những nội dung bên dưới:

  1. Dẫn nhập
  2. Interface là gì? Và cú pháp khai báo
  3. Các đặc điểm của interface
  4. Demo code minh họa cách sử dụng
1. Dẫn nhập
1. Dẫn nhập

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
<access_modifier> interface <tên_interface> <: tên_base_interface>
{

    // interface member

}

Trong đó:

  • <access_modifier> : 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.
  • <tên_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.

Ví dụ:

// 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
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, indexersevents 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 classesstructs, 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
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 MinhHoangBlog để 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 MinhHoangBlog
{
    interface IRank
    {
		// Khai báo prototype hàm xếp loại
        string Ranking(float score);
    }
}


■ Nội dung file Apolo.cs

namespace MinhHoangBlog
{
	// 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 MinhHoangBlog
{
	// 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 MinhHoangBlog
{
    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ả chương trình

Kết quả chương trình


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 ILandAnimalIWaterAnimal để đị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 MinhHoangBlog
{    
    interface ILandAnimal
    {
		// Ếch: Di chuyển trên mặt đất là Nhảy
		void Jump();
    }
}


■ Nội dung file IWaterAnimal.cs

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


■ Nội dung file Frog.cs

using System;

namespace MinhHoangBlog
{
	// 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 MinhHoangBlog
{
    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ả chương trình

Kết quả chương trình


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 MinhHoangBlog để 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 ILandAnimalIWaterAnimal để đị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 MinhHoangBlog
{
	interface ILandAnimal
	{
		void Move();
	}
}


■ Nội dung file IWaterAnimal.cs

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


■ Nội dung file Frog.cs

– Lúc này, vì 2 interface ILandAnimalIWaterAnimal 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 MinhHoangBlog
{
	// 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 ILandAnimalIWaterAnimal 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 MinhHoangBlog
{
	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ả chương trình

Kết quả chương trình

Cảm ơn bạn đã theo dõi. Đừng ngần ngại hãy cùng thảo luận với chúng tôi! Minh Hoàng Blog | Nào cùng vui hehe


Giới thiệu

Minh Hoàng

Xin chào, tôi là Hoàng Ngọc Minh, hiện đang làm BrSE, tại công ty Toyota, Nhật Bản. Những gì tôi viết trên blog này là những trải nghiệm thực tế tôi đã đúc rút ra được trong cuộc sống, quá trình học tập và làm việc. Các bài viết được biên tập một cách chi tiết, linh hoạt để giúp người đọc có thể tiếp cận một cách dễ dàng nhất. Hi vọng nó sẽ có ích hoặc mang lại một góc nhìn khác cho bạn[…]

Bình luận của bạn

3 Comments cho bài viết "Giới thiệu interface trong lập trình C#"

avatar
Sắp xếp theo:   Mới nhất | Cũ nhất | Thích nhiều nhất
trackback

[…] Alt + Shift + F10 + Enter: Hiện thực các phương thức kế thừa từ Abstract class hay Interface. […]

trackback

[…] – Chỉ cho phép đơn kế thừa, tức là một lớp chỉ được phép kế thừa từ một lớp khác. (vậy làm thế nào một lớp có thể sử dụng được các thuộc tính và phương thức của nhiều lớp khác nhau? Sẽ được trình bày trong bài Interface trong lập trình C#). […]

trackback

[…] sự giống và khác nhau giữa hai khái niệm này và biết được khi nào nên dùng interface, khi nào nên dùng abstract class […]

wpDiscuz
Chúc bạn có một cuộc sống ngoại hạng!