Tính đa hình (Polymorphism) là một trong 4 tính chất trụ cột của lập trình hướng đối tượng OOP.
Nếu chưa hiểu rõ về lập trình hướng đối tượng thì bạn nên tham khảo bài viết dưới đây trước:
Tính đa hình là khả năng một đối tượng có thể thực hiện một tác vụ theo nhiều cách khác nhau. Đa hình gồm 2 loại là đa hình tĩnh và đa hình động.
Đa hình tĩnh còn gọi là đa hình tại thời điểm biên dịch (compile time). C# cung cấp hai kỹ thuật để thực hiện đa hình tĩnh là:
Bạn có thể thực hiện nạp chồng phương thức bằng cách tạo nhiều phương thức cùng tên nhưng khác nhau về kiểu dữ liệu và/hoặc số lượng đối số trong danh sách đối số. Bạn không thể nạp chồng phương thức khi phương thức chỉ khác nhau về kiểu trả về.
Ví dụ sau đây cho thấy sử dụng phương thức Resize() để thay đổi kích thước chiều dài và rộng của hình chữ nhật:
using System;
namespace BoxApplication
{
class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
// overload method
public void Resize(double sameSize)
{
Width = sameSize;
Height = sameSize;
}
public void Resize(int width, int height)
{
Width = width;
Height = height;
}
public void Resize(double width, double height)
{
Width = width;
Height = height;
}
public double GetArea()
{
return Width * Height;
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle rectangle1 = new Rectangle(6.0, 7.0);
Console.WriteLine("Area = {0} x {1} = {2}", rectangle1.Width, rectangle1.Height, rectangle1.GetArea());
rectangle1.Resize(5.0);
Console.WriteLine("Area = {0} x {1} = {2}", rectangle1.Width, rectangle1.Height, rectangle1.GetArea());
Console.ReadKey();
}
}
}
Kết quả khi biên dịch và chạy chương trình trên:
Area = 6 x 7 = 42
Area = 5 x 5 = 25
Bạn có thể định nghĩa lại hoặc nạp chồng hầu hết các toán tử tích hợp sẵn có trong C#.
Do đó, một lập trình viên cũng có thể sử dụng các toán tử với các kiểu do người dùng định nghĩa.
Nạp chồng toán tử là các phương thức có tên đặc biệt với từ khóa operator và theo sau là ký hiệu cho toán tử được chỉ định.
Tương tự như bất kỳ phương thức nào khác, nạp chồng toán tử có kiểu trả về và danh sách đối số.
Ví dụ: đi qua chức năng sau:
public static Box operator +(Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
Hàm trên thực hiện nạp chồng toán tử cộng (+) cho lớp Box do người dùng định nghĩa. Nó cộng các thuộc tính của hai đối tượng Box và trả về đối tượng Box kết quả.
Thực hiện nạp chồng toán tử
Chương trình sau đây cho thấy việc thực hiện đầy đủ:
using System;
namespace BoxApplication
{
class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
// overload operator
public static Rectangle operator +(Rectangle a, Rectangle b)
{
return new Rectangle(a.Width + b.Width, a.Height + b.Height);
}
public static Rectangle operator -(Rectangle a, Rectangle b)
{
return new Rectangle(a.Width - b.Width, a.Height - b.Height);
}
// other methods
public double GetArea()
{
return Width * Height;
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle rectangle1 = new Rectangle(3.0, 5.0);
Rectangle rectangle2 = new Rectangle(2.0, 4.0);
// use operator +
Rectangle rectangle3 = rectangle1 + rectangle2;
Console.WriteLine("Area = {0} x {1} = {2}", rectangle3.Width, rectangle3.Height, rectangle3.GetArea());
Console.ReadKey();
}
}
}
Kết quả khi biên dịch và chạy chương trình trên:
Area = 5 x 9 = 45
Toán tử quá tải và không quá tải
Bảng sau mô tả khả năng nạp chồng của các toán tử trong C#:
STT | Toán tử & Mô tả |
---|---|
1 | +, -,!, ~, ++, -
Các toán tử đơn nguyên này có một toán hạng và có thể nạp chồng. |
2 | +, -, *, /,%
Các toán tử nhị phân này có một toán hạng và có thể nạp chồng. |
3 | == ,! =, <,>, <=,> =
Các toán tử so sánh có thể nạp chồng. |
4 | &&, ||
Các toán tử logic có điều kiện không thể nạp chồng trực tiếp. |
5 | + =, - =, * =, / =,% =
Các toán tử gán không thể nạp chồng. |
6 | =,.,?:, ->, new, is, sizeof, typeof
Các toán tử không thể nạp chồng. |
Đa hình động là đa hình lúc thực thi (runtime). C# cho phép bạn tạo các lớp trừu tượng (abstract class) được sử dụng để cung cấp triển khai lớp một phần của giao diện.
Việc thực hiện được hoàn thành khi một lớp dẫn xuất kế thừa từ nó. Các lớp trừu tượng chứa các phương thức trừu tượng (abstract method) sẽ được thực hiện bởi lớp dẫn xuất.
Dưới đây là ví dụ về đa hình động trong C#:
using System;
namespace PolymorphismApplication
{
abstract class Shape
{
public abstract int GetArea();
}
class Rectangle : Shape
{
public int Width { get; set; }
public int Height { get; set; }
public Rectangle(int width, int height)
{
Width = width;
Height = height;
}
public override int GetArea()
{
return Width * Height;
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle rectangle = new Rectangle(10, 7);
Console.WriteLine("Area: {0}", rectangle.GetArea());
Console.ReadKey();
}
}
}
Kết quả khi biên dịch và chạy chương trình trên:
Area: 70
Hiểu được sự khác biệt giữa các loại mảng trong C# sẽ giúp bạn chọn cấu trúc dữ liệu chính xác cho mọi trường hợp.
Trong bài viết này, tôi sẽ so sánh sự khác biệt về hiệu suất giữa struct và class trong C#: Ai nhanh hơn.
Mục tiêu của bài viết này là cung cấp một danh sách không đầy đủ các code mẫu cần tránh, vì chúng rủi ro hoặc performance kém.
Hướng dẫn này sẽ giúp bạn tìm hiểu về đọc ghi file (File I/O) trong C# và sử dụng các lớp tiện ích để đọc ghi file.