C# - C Sharp: Partial
Giả sử rằng có một tổ chức lớn trong đó bộ phận IT được chia thành hai cơ sở và Melbourne và Sydney. Nhiệm vụ bây giờ là phải thu thập dữ liệu của cả hai cơ sở. Các khách hàng của tổ chức Chức năng
Giả sử ta có một lớp hoặc một structure rất lớn với rất nhiều thành phần được định nghĩa bên trong, lúc này ta cần phải tìm cách chia lớp hay cấu trúc đó thành những file nhỏ để tiện quản lý, nhưng phải đảm bảo sau khi chia nhỏ thì có thể lại kết hợp lại được khi muốn thực thi chương trình. Partial là cách thức mà C# cho phép ta chia nhỏ một lớp hay cấu trúc thành những phần nhỏ hơn.
Đặc điểm và ưu điểm của partial
Ta có thể áp dụng partial cho class, structure và interface. Dưới đây là một số đặc điểm cũng như ưu điểm của partial:
· Tách mã tạo khỏi mã ứng dụng.
· Dễ phát triển và bảo trì code hơn.
· Dễ gỡi lỗi (debug) hơn.
· Ngăn ngừa lập trình viên có thể vô tình sửa đổi mã lệnh.
Lưu ý: C# không hỗ trợ partial để định nghĩa kiểu liệt kê, tuy nhiên, ta có thể áp dụng partial cho kiểu generic.
Hợp nhất các thành phần trong quá trình biên dịch
Sau khi dùng partial để chia nhỏ class, structure hay interface thì ta có thể đặt chúng ở những vị trí khác nhau, và ta hoàn toàn có thể hợp nhất chúng tại thời điểm biên dịch chương trình. Những thành phần được chia nhỏ có thể gồm:
· Các chú thích XML
· Các Interface
· Các tham số kiểu generic
· Các biến lớp
· Các biến cục bộ
· Các phương thức
· Các Property
Partial Class
Ta có thể sử dụng partial để chia lớp thành những file nhỏ hơn, ví dụ ta muốn chia lớp thành hai file, một file chứa các thành phần private và một file chứa các thành phần public thì rõ ràng hiệu quả quản lý cũng như bảo mật sẽ tốt lên nhiều; hơn nữa điều này cũng cho phép các nhà phát triển cùng một lúc làm việc trên khác thành phần khác nhau của cùng một lớp, và sẽ giúp tăng tốc độ hoàn thành.
Ví dụ:
Trong ví dụ trên, lớp StudentDetails được chia thành hai file là StudentDetails.cs và StudentDetails2.cs, trong đó StudentDetails.cs chứa phương thức Display(), còn StudentDetails2.cs chứa các biến lớp và một hàm tạo; lớp phương thức Main() tạo một thể hiện của lớp StudentDetails và gọi phương thức Display().
Output:
Partial Method
Xét một lớp partial có tên Shape và lớp này được tách thành hai file. Xét một phương thức có tên Create() và có một dấu hiệu trong lớp Shape.
Lớp partial Shape chứa phần định nghĩa của phương thức Create() trong file Shape.cs. Phần còn lại của lớp partial Shape được đặt trong file RealShape.cs và nó chứa phần thực thi của phương thức Create().
Vậy thì, phương thức Create() là phương thức partial và được định nghĩa ở hai file.
Một phương thức partial là một phương thức mà phần khai báo của nó có kiểu partial. Phương thức có thể tùy chọn thực thi trong phần khác nhau của lớp partial hoặc kiểu hoặc cùng phần của lớp hoặc kiểu.
Dưới đây là ví dụ minh họa việc khai báo và định nghĩa phương thức partial có tên Create():
Khai báo phương thức Create():
namespace Demo { /// <summary> /// Lớp Shape là lớp partial và trong nó định nghĩa một phương thức partial /// </summary> public partial class Shape { partial void Create(); } }
Định nghĩa phương thức Create():
using System; namespace Demo { public partial class Shape { partial void Create() { Console.WriteLine("Creating Shape"); } public void Test() { Create(); } } class Program { static void Main(String[] args) { Shape s = new Shape(); s.Test(); } } }
Ta cũng có thể đặt phần khai báo và phần thực thi của phương thức Create() trong cùng một phần của Shape.
Bằng cách tách phần định nghĩa và phần thực thi hai tệp thì hai nhà phát triển có thể làm việc trên chúng hoặc thậm chí sử dụng công cụ tạo mã để tạo định nghĩa của phương thức.
Ví dụ sau thể hiện việc khai báo, định nghĩa và thực thi phương thức Create() trong cùng một file.
using System; namespace PartialTest { /// <summary> /// Lớp Shape chứa cả phần định nghĩa và thực thi của phương thức Create(). /// </summary> public partial class Shape { partial void Create(); partial void Create() { Console.WriteLine("Creating Shape"); } public void Test() { Create(); } } class Program { static void Main(String[] args) { Shape s = new Shape(); s.Test(); } } }
Ta chỉ có thể khai báo phương thức Create() trong một phần của lớp Shape và không có phần thực thi Create() ở bất kỳ đâu. Trong trường hợp đó thì trình biên dịch sẽ loại bỏ tất cả các tham chiếu đến Create(), bao gồm bất kỳ lời gọi phương thức nào.
Phương thức partial phải luôn bao gồm từ khóa partial.
Các phương thức partial chỉ có thể được định nghĩa trong một lớp hoặc kiểu partial.
Nếu lớp chứa định nghĩa hoặc thực thi của phương thức partial mà không có từ khóa partial thì lỗi thời gian biên dịch (compile-time) sẽ xuất hiện.
Một số hạn chế khi làm việc với phương thức partial như sau:
- Từ khóa partial là bắt buộc khi định nghĩa hoặc triển khai một phương thức partial
- Phương thức partial phải có kiểu trả về là void
- Ngầm định là private
- Phương thức partial có thể trả về ref nhưng không trả về out
- Phương thức partial không được chứa bất kỳ bổ từ truy cập nào như public, private, ... hoặc các từ khóa như virtual, abstract, sealed, ...
Phương thức từng phần hữu ích khi bạn có một phần mã lệnh được tạo tự động bởi một công cụ hoặc IDE và muốn tùy chỉnh các phần khác của mã lệnh.
Tính hữu ích của partial
Một dự án lớn trong một tổ chức sẽ có liên quan đến việc tạo ra nhiều struct, class và interface.
Nếu những phần này được lưu trữ trong một tệp duy nhất thì việc sửa đổi và bảo trì chúng trở nên rất khó khăn.
Ngoài ra, nhiều lập trình viên làm việc trong dự án không thể sử dụng tệp cùng một lúc để sửa đổi.
Do đó, kiểu partial có thể được sử dụng để chia thành các tệp riêng biệt, cho phép các lập trình viên làm việc trên chúng một cách đồng thời.
Thừa kế lớp partial
Lớp partial có thể được kế thừa giống như bất kỳ lớp nào khác trong C#.
Nó có thể chứa các phương thức ảo được định nghĩa trong các tệp khác nhau, có thể được ghi đè trong các lớp dẫn xuất của nó.
Ngoài ra, lớp partial có thể được khai báo như một lớp trừu tượng bằng cách sử dụng từ khóa virtual.
Các lớp trừu tượng partial có thể được kế thừa.
Ví dụ sau minh họa cách kế thừa một lớp partial:
Đoạn mã sau lưu trong file Geometry.cs:
namespace Demo { abstract partial class Geometry { public abstract double Area(double val); } }
Đoạn mã sau lưu vào file Cube.cs:
using System; namespace Demo { abstract partial class Geometry { public virtual void Volume(double val) { } } class Cube : Geometry { public override double Area(double side) { return 6 * (side * side); } public override void Volume(double side) { Console.WriteLine("Volume of cube: " + (side * side)); } static void Main(string[] args) { double number = 20.56; Cube objCube = new Cube(); Console.WriteLine("Area of Cube: " + objCube.Area(number)); objCube.Volume(number); } } }
Trong ví dụ trên:
Lớp trừu tượng partial Geometry được định nghĩa trên hai tệp C#, nó định nghĩa một phương thức trừu tượng gọi là Area() và một phương thức ảo gọi là Volume(), cả hai phương thức này đều được kế thừa trong lớp dẫn xuất gọi là Cube.
Kết quả:
Area of Cube: 2536.2816
Volume of cube: 422.7136