Lớp và Thừa kế Chúng ta đã được xem cách sử dụng lớp trong chương 2 nhưng để nắm được mối liên hệ giữa các chương, chúng tôi sẽ tóm tắt một vài khái niệm về lớp. Lớp trong C# được định nghĩa với cú pháp sau: class MyClass { private int someField; public string SomeMethod(bool parameter) { } } Các lớp bao gồm nhiều thành viên, mỗi thành viên là thuật ngữ(term) dùng để chỉ đến một dữ liệu hay một chức năng nào đó được định nghĩa trong lớp đó. Ví dụ chúng ta dùng thuật ngữ Function để chỉ những thành viên chứa mã như các phương thức(methods), các thuộc tính(properties), constructor, hay các nạp chồng toán hạng(Operator Overloads). Tất cả các lớp trong C# là những kiểu tham khảo. Tức là khi bạn khai báo một kiểu lớp thì có một biến lưu trữ sự tham khảo đến một thể hiện (instance) của lớp đó. Và sử dụng lệnh new để tạo ra một đối tượng. Ví dụ tạo ra đối tượng myObject như sau: MyClass myObject; myObject = new MyClass(); Tuy nhiên bạn có thể khai báo và khởi tạo đối tượng cùng một lúc. MyClass myObject = new MyClass(); Đơn thừa kế: C# hỗ trợ đơn thừa kế giữa các lớp. Một lớp có thể thừa hưởng những thuộc tính và phương thức từ một lớp khác. Cú pháp: class MyDerivedClass : MyBaseClass { // functions and data members here } Cú pháp này khác với C++ về phạm vi, không có bổ từ truy cập(access modifier). Tức là C# không hỗ trợ như C++ về các khái niệm thừa kế public hay private vì nó làm ngôn ngữ thêm phức tạp. Trong thực tế thì thừa kế private rất ít được sử dụng. Trong C# một lớp bắt buột phải thừa kế từ một lớp nào đó. C# hỗ trợ một lớp cơ sở toàn diện gọi là System.Object. Phương thức nạp chồng(Overloading): C# hỗ trợ phương thức nạp chồng với một vài dạng phương thức khác nhau về những đặc tính sau: tên, số lượng thông số, và kiểu thông số. Nhưng nó không hỗ trợ những thông số mặc định như C++ và VB. Một cách đơn giản là bạn khai báo những phương thức cùng tên nhưng khác số lượng và kiểu của thông số: class ResultDisplayer { void DisplayResult(string result) { // implementation } void DisplayResult(int result) { // implementation } } Bởi vì C# không hỗ trợ những thông số tuỳ chọn nên bạn cần sử dụng những phương thức nạp chồng để đạt được cùng một hiệu quả: class MyClass { int DoSomething(int x) // want 2nd parameter with default value 10 { DoSomething(x, 10); } int DoSomething(int x, int y) { // implementation } } Trong bất kỳ một ngôn ngữ nào, phương thức nạp chồng có thể đem đến một lỗi nghiêm trọng nếu nó bị gọi sai. Trong chương tới ta sẽ bàn cách để tránh đều đó. Trong C# có một vài điểm khác nhỏ về thông số trong các phương thức nạp chồng cần biết như sau: Nó không chấp nhận hai phương thức chỉ khác nhau về kiểu trả về. Nó không chấp nhận hai phương thức chỉ khác nhau về đặc tính của một thông số đang được khai báo như ref hay out. Phương thức Overriden và Hide: Bằng cách khai báo virtual trong một hàm ở lớp cơ sở thì cho phép hàm đó được overriden trong bất kỳ một lớp thừa hưởng nào. class MyBaseClass { public virtual string VirtualMethod() { return "This method is virtual and defined in MyBaseClass"; } } Như ví dụ trên, tức là ta có thể tạo ra một sự thực thi khác của VirtualMethod() trong một lớp thừa hưởng của MyBaseClass. Và khi gọi phương thức trong một thể hiện của lớp thừa hưởng thì phương thức của lớp thừa hưởng sẽ được thi hành mà không quan tâm đến phương thức đó ở lớp cơ sở. Khác với C++ và Java, trong C# những hàm không được khai báo virtual mặc định mà bạn phải khai báo virtual một cách rõ ràng và khi một hàm muốn override một hàm khác thì phải sử dụng từ khoá override: class MyDerivedClass : MyBaseClass { public override string VirtualMethod() { return "This method is an override defined in MyDerivedClass"; } } Những trường thành viên(member fields) và những hàm tĩnh thì không được khai báo Virtual. Nếu một phương thức có cùng đặc tính trong cả hai khai báo ở lớp cơ sở và lớp thừa hưởng nhưng các phương thức này thì không khai báo virtual hay overriden thì sẽ được gọi là: "lớp thừa hưởng hide lớp cơ sở đó". Kết quả là: phương thức nào được gọi phụ thuộc vào kiểu của biến được sử dụng để tham khảo đến thể hiện, chứ không phải kiểu của chính thể hiện đó. Trong hầu hết mọi trường hợp bạn luôn thích override một phương thức hơn là hide nó. Bởi vì hide dễ gây ra những lỗi nghiêm trọng. Nhưng cú pháp C# được thiết kế để bảo đảm cho những nhà phát triển sẽ được cảnh báo trong thời gian biên dịch về vấn đề nghiêm trọng này. Nếu bạn tạo ra hai phương thức hoàn toàn giống nhau ở cả lớp thừa hưởng và lớp cơ sở mà không có khai báo virtual và override thì bạn sẽ bị cảnh báo trong khi biên dịch. Trong C#, bạn nên sử dụng từ khoá new để đảm bảo bạn muốn hide phương thức đó. Gọi các phiên bản cơ sở của các chức năng(base Versions of Functions): Trong C# có một cú pháp đặc biệt để gọi những phiên bản cơ sở của một phương thức từ một lớp thừa hưởng. Cú pháp : base.<methodname>(). Ví dụ: class CustomerAccount { public virtual decimal CalculatePrice() { // implementation } } class GoldAccount : CustomerAccount { public override decimal CalculatePrice() { return base.CalculatePrice() * 0.9M; } Các lớp và hàm Abstract : C# cho phép cả lớp và phương thức có thể khai báo abstract. Một lớp abstract không được thể hiện và một phương thức abstract không được thực thi mà phải được overriden trong bất kỳ lớp thừa hưởng không abstract nào. Một phương thức abstract sẽ tự động được khai báo virtual. Nếu một lớp có phương thức abstract thì nó cũng là lớp abstract và được khai báo như sau: abstract class Building { public abstract decimal CalculateHeatingCost(); // abstract method } Sealed các lớp và phương thức: C# cho phép các lớp và phương thức được khai báo sealed. Nếu là lớp có nghĩa là bạn không được quyền thừa kế lớp đó, nếu là phương thức tức là bạn không được phép override nó. C# sử dụng từ khoá sealed trước tên lớp và phương thức: sealed class FinalClass { // etc } class DerivedClass : FinalClass // wrong. Will give compilation error { // etc } class MyClass { public sealed override void FinalMethod() { // etc. } } class DerivedClass : MyClass { public override void FinalMethod() // wrong. Will give compilation error { } } Những bổ từ truy cập(access modifiers): Trong C# cung cấp một số lượng những bổ từ để cho biết sự tồn tại của một thành viên của một lớp. C# có 5 bổ từ như sau: Accessibility Mô tả public Biến và phương thức có thể được truy cập từ bất kỳ nơi đâu. internal Biến và phương thức chỉ có thể được truy cập trong cùng mộ t gói. protected Biến hay phương thức chỉ có thể đư ợc truy cập từ kiểu của nó hay từ những kiểu thừa kế kiểu đó. protected internal Biến hay phương thức có thể đư ợc truy cập từ gói hiện tại, hay từ những kiểu thừa kế kiểu hiện tại. private Biến hay phương thức chỉ có thể truy cập từ trong kiểu của nó. . báo và khởi tạo đối tượng cùng một lúc. MyClass myObject = new MyClass(); Đơn thừa kế: C# hỗ trợ đơn thừa kế giữa các lớp. Một lớp có thể thừa hưởng những thuộc tính và phương thức từ một lớp. Lớp và Thừa kế Chúng ta đã được xem cách sử dụng lớp trong chương 2 nhưng để nắm được mối liên hệ giữa các chương, chúng tôi sẽ tóm tắt một vài khái niệm về lớp. Lớp trong C#. các khái niệm thừa kế public hay private vì nó làm ngôn ngữ thêm phức tạp. Trong thực tế thì thừa kế private rất ít được sử dụng. Trong C# một lớp bắt buột phải thừa kế từ một lớp nào đó. C#