Trong bài viết này, chúng ta sẽ cùng tìm hiểu về từ khoá static trong lập trình hướng đối tượng C#.
1. Đặc điểm của thành viên tĩnh
– Bình thường các thuộc tính, phương thức sẽ có đặc điểm:
- Chỉ có thể sử dụng sau khi khởi tạo đối tượng.
- Dữ liệu thuộc về riêng mỗi đối tượng (xét cùng 1 thuộc tính thì các đối tượng khác nhau thì thuộc tính đó sẽ mang các giá trị khác nhau).
- Được gọi thông qua tên của đối tượng.
– Đôi lúc người lập trình mong muốn 1 thuộc tính nào đó được dùng chung cho mọi đối tượng (chỉ được cấp phát 1 vùng nhớ duy nhất). Từ đó khái niệm thành viên tĩnh ra đời.
– Đặc điểm của thành viên tĩnh:
- Được khởi tạo 1 lần duy nhất ngay khi biên dịch chương trình.
- Có thể dùng chung cho mọi đối tượng.
- Được gọi thông qua tên lớp.
- Được huỷ khi kết thúc chương trình.
– Có 4 loại thành viên tĩnh chính:
- Biến tĩnh (static variable).
- Phương thức tĩnh (static method).
- Phương thức khởi tạo tĩnh (static constructor).
- Lớp tĩnh (static class).
– Để khai báo một thành viên tĩnh ta sử dụng từ khoá static đặt trước tên biến, tên phương thức hoặc tên lớp.
– Từ khoá static ngụ ý rằng: chỉ có một instance của thành viên tồn tại cho một class.
2. Biến tĩnh
– Cú pháp khai báo:
<phạm vi truy cập> static <kiểu dữ liệu> <tên biến> = <giá trị khởi tạo>;
(giá trị khởi tạo có thể khởi tạo hoặc không cần)
– Một số đặc điểm của biến tĩnh:
- Biến static có thể được khởi tạo bên ngoài hàm thành viên, hoặc ngoài định nghĩa class, hoặc trong định nghĩa class.
- Là biến dùng chung cho mọi đối tượng thuộc lớp.
- Được khởi tạo vùng nhớ một lần duy nhất ngay khi chương trình được nạp vào bộ nhớ để thực thi. Và nó có vùng nhớ riêng, không bị thay đổi.
- Được gọi trực tiếp thông qua tên lớp mà không cần tạo đối tượng của lớp, chính vì điều này mà biến static thường được sử dụng để định nghĩa cho các hằng số (constant).
– Ví dụ:
namespace MinhHoangBlog
{
class StaticVariable
{
static void Main(string[] args)
{
// Khai báo 2 đối tượng Student
Student student1 = new Student();
Student student2 = new Student();
// Khởi tạo giá trị cho biến static bên ngoài định nghĩa class
// Sử dụng trực tiếp tên class để truy cập vào biến.
Student.Ethnic = "KINH";
student1.GetEthnic();
student2.GetEthnic();
Console.ReadKey();
}
}
public class Student
{
// Khai báo biến tĩnh
public static string Ethnic;
public void GetEthnic()
{
Console.WriteLine("Ethnic: " + Ethnic);
}
}
}[/code]
※ Thông qua ví dụ trên chúng ta thấy được rằng: student1 và student2 là 2 đối tượng khác nhau của class Student, nhưng chúng ta đã khai báo static cho biến Ethnic của class Student, nên tất cả các đối tượng của nó sẽ dùng chung một giá trị của biến static Ethnic.
3. Phương thức tĩnh
– Cú pháp khai báo:
<phạm vi truy cập> static <kiểu dữ liệu trả về> <tên phương thức>; { // nội dung phương thức }
– Một số đặc điểm của phương thức tĩnh:
- Static method là một phương thức dùng chung của lớp. Được gọi thông qua tên lớp và không cần khởi tạo bất kỳ đối tượng nào, từ đó tránh việc lãng phí bộ nhớ.
- Hỗ trợ trong việc viết các hàm tiện ích của thư viện để sử dụng lại.
- Trong phương thức có sử dụng biến static thì phương thức đó cũng phải được khai báo là static.
– Ví dụ:
namespace MinhHoangBlog
{
class StaticMethod
{
static void Main(string[] args)
{
// Sử dụng trực tiếp tên class để truy cập vào static method.
// mà không cần khởi tạo đối tượng student
Student.PrintName("Minh Hoang", "Blog");
Student.PrintName("Welcome to", "www.minhhn.com");
Console.ReadKey();
}
}
public class Student
{
// Khai báo phương thức tĩnh
public static void PrintName(string in_firstName, string in_lastName)
{
string name = string.Format("{0} {1}", in_firstName, in_lastName);
Console.WriteLine("Student name: " + name);
}
}
}[/code]
4. Phương thức khởi tạo tĩnh
– Cú pháp khai báo:
static <tên lớp>; { // nội dung của hàm dựng, hàm khởi tạo constructor }
– Một số đặc điểm của phương thức khởi tạo tĩnh:
- Không được phép khai báo phạm vi truy cập. Nếu khai báo chương trình sẽ báo lỗi khi biên dịch.
- Static constructor sẽ được gọi một lần duy nhất khi chương trình được nạp vào bộ nhớ để thực thi như là một cách để ta thiết lập một số thông số theo ý muốn trước khi có bất kỳ đối tượng nào được tạo ra.
- Constructor tĩnh cũng giống phương thức tĩnh nên không thể gọi các thuộc tính không phải static.
– Ví dụ: Giả sử bạn có một biến tĩnh colorDay dùng để lưu trữ giá trị màu sắc khác nhau tùy theo thứ của ngày trong tuần, chẳng hạn:
- Thứ 2: màu xanh dương
- Thứ 3: màu đỏ
- Thứ 4: màu tím
- Thứ 5: màu hồng
- Thứ 6: màu đen
- Thứ 7: màu xanh lá
- Chủ nhật: màu vàng
– Và bạn muốn khởi tạo giá trị cho biến tĩnh colorDay, nhưng không thể khởi tạo bằng cách gán trực tiếp màu red như sau, vì làm thế thì tất cả các ngày trong tuần đều chỉ cho một màu red:
public static string colorDay= "Red";
– Và bạn cũng không thể khởi tạo biến tĩnh colorDay này trong constructor bình thường được. Vì constructor bình thường chỉ được gọi khi có đối tượng được khởi tạo.
– Trường hợp này thì constructor tĩnh là 1 giải pháp đơn giản nhưng hiệu quả.
namespace MinhHoangBlog
{
class StaticConstructor
{
static void Main(string[] args)
{
// Sử dụng trực tiếp tên class truy cập vào static variable.
// mà không cần khởi tạo đối tượng ColorSample
Console.WriteLine("Màu của ngày hôm này là: " + ColorSample.colorDay);
Console.ReadKey();
}
}
public class ColorSample
{
// Khai báo biến tĩnh
public static string colorDay;
// Khai báo phương thức khởi tạo tĩnh (static constructor)
static ColorSample()
{
// Lấy ngày giờ hiện tại của hệ thống
DateTime now = DateTime.Now;
// Lấy màu tương ứng với ngày trong tuần
switch (now.DayOfWeek)
{
case DayOfWeek.Monday:
colorDay = "Blue";
break;
case DayOfWeek.Tuesday:
colorDay = "Red";
break;
case DayOfWeek.Wednesday:
colorDay = "Purple";
break;
case DayOfWeek.Thursday:
colorDay = "Pink";
break;
case DayOfWeek.Friday:
colorDay = "Black";
break;
case DayOfWeek.Saturday:
colorDay = "Green";
break;
case DayOfWeek.Sunday:
colorDay = "Yellow";
break;
}
}
}
}[/code]
5. Lớp tĩnh
- Static class chỉ chứa các thành phần tĩnh (biến tĩnh, phương thức tĩnh), và đều được truy cập thông qua tên lớp.
- Không thể khai báo, khởi tạo 1 đối tượng thuộc lớp tĩnh.
- Static class thường được dùng với mục đích khai báo một lớp tiện ích chứa các hàm tiện ích hoặc hằng số.
Trong C# có rất nhiều lớp tiện ích sử dụng lớp tĩnh, phương thức tĩnh. Chẳng hạn như một lớp rất hay sử dụng đó là lớp String: