NHỮNG KHÁI NIỆM CƠ BẢN CỦA LẬP TRÌNH HƯỚNG ĐỐI
TƯỢNG
Khái niệm:
Lập trình hướng đối tượng gọi tắt là OOP (Object-Oriented Programming) là kĩ
thuật hỗ trợ công nghệ đối tượng. OOP được xem là ngôn ngữ lập trình giúp
tăng năng suất lập trình, giúp đơn giản hóa việc lập trình và mở rộng chức
năng lập trình, giúp dễ dàng bảo trì và mở rộng các chức năng phần mềm
bằng các cho phép lập trình viên có thể tương tác với các đối tượng phần
mêm ở mức cao hơn. Phương pháp lập trình hướng đối tượng còn được xem
là dễ tiếp thu hơn là những phương pháp trước đó.
(Một sự hiểu đơn giản là đây là phương pháp giúp giảm nhẹ cho
việc lập trình, giúp cho người lập trình tạo ra những đối tượng mà
cho phép các đội tượng bên ngoài tương tác lên nó như tương
tác tới một đối tượng vật lý.)
(Trên là cái hiểu nôm na của mình về hướng đối tượng. Cái đặc
biệt của hướng đối tượng là các tính chất của nó, khi hiểu rõ các
tính chất của hướng đối tượng sẽ giúp bạn bước vào sử dụng nó
linh động hơn.)
MỘT SỐ KHÁI NIỆM VỀ HƯỚNG ĐỐI TƯỢNG
•
Cú pháp thừa kế trong C#, các chức năng ảo, và các tính năng liên quan.
•
Những phương thức nạp chồng: C# cho phép bạn định nghĩa những dạng
khác nhau của một phương thức trong một lớp. Trình biên dịch sẽ tự động
chọn phương thức nào thích hợp nhất dựa vào tham số truyền vào của nó.
•
Construction và Destruction: Nó chỉ rõ cách mà một đối tượng khởi tạo sẽ
có một số hành động tự động kèm theo và tự động giải phóng khi kết thúc.
•
Struct: là những kiểu giá trị mà cung cấp những tiện nghi khi bạn cần một
số tính năng của một lớp mà không cần phải vất vả tạo ra một thực thể lớp
cho phức tạp.
•
Nạp chồng toán hạng : sẽ kiểm tra cách để định nghĩa những toán hạng
cho lớp của bạn.
•
Indexers: Cho phép một lớp được xử lý chỉ mục khi nó là một mảng và có
thể đơn giản hoá cách sử dụng những lớp chứa các tập đối tượng.
•
Giao diện : C# hỗ trợ thừa kế giao diện tốt như thừa kế thực thi, bạn sẽ
được biết rõ hơn ở phần sau.
LớpvàThừakế
-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();
-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).
Đơnthừakế
•
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
{
// chức năng và dữ liệu thành viên ở đây
}
•
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. (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ươngthứcnạ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)
{
// thực hiện
}
void DisplayResult(int result)
{
// thực hiện
}
}
Phươngthứcnạp
chồng(Overloading)
•
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 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ươngthứcOverridenvà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()
{
turn " Phương pháp này là ảo và quy định tại 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 " Phương pháp này là ảo và quy định tại MyBaseClass ";
}
}
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
PhươngthứcOverridenvàHide
•
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 đó.
•
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ọicácphiênbảncơsởcủacácchức
năng(baseVersionsofFunctions)
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()
{
// thực hiện
}
}
class GoldAccount : CustomerAccount
{
public override decimal CalculatePrice()
{
return base.CalculatePrice() * 0.9M;
}
CáclớpvàhàmAbstract:
-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(); // phương
pháp trừu tượng
}
Sealedcáclớpvàphươngthứ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
Thuộctính(properties)
•
Thủ tục get không có tham số và phải trả về cùng kiểu với thuộc tính đã
được khai báo
private string foreName;
public string ForeName
{
get
{
return foreName;
}
Set
{
if (value.Length > 20)
// Code ở đây để có hành động sửa lỗi
// ném trả 1 ngoại lệ
else
foreName = value;
}
}
Khác với VB các thủ tục get và set được định nghĩa như là những hàm riêng biệt, trong C# chúng được khai báo
cùng nhau trong một khai báo thuộc tính đơn.Trong VB bạn khai báo tường minh tham số cho thủ tục set và
có thể chọn tên của nó, nhưng ngược lại trong C# tham số này hoàn toàn giả lập và luôn mang tên là value.
Bổtừtruycập:
C# không cho phép cài đặt những bổ từ khác nhau cho thủ tục set và get. Nếu
bạn muốn tạo ra một thuộc tính có public để đọc nhưng lại muốn hạn chế
protected trong gán thì đầu tiên bạn phải tạo thuộc tính chỉ đọc với bổ từ
public sau đó tạo một hàm set() với bổ từ protected ở bên ngoài thuộc tính
đó.
public string ForeName
{
get
{
return foreName;
}
}
protected void SetForeName(string value)
{
if (value.Length > 20)
// Code ở đây để có hành động sửa lỗi
// ném trả 1 ngoại lệ
else
foreName = value;
}
ThuộctínhVirtualvàAbstract
C# cho phép bạn tạo một thuộc tính virtual hay
abstract. Để khai báo một thuộc tính virtual,
overriden hay abstract bạn chỉ cần thêm từ
khoá đó trong lúc định nghĩa thuộc tính. Ví dụ
để tạo một thuộc tính abstract thì cú pháp như
sau:
public abstract string ForeName
{
get;
set;
}
Lớpđốitượng
Giaodiện(Interfaces)
- C# hỗ trợ giao diện (Interfaces). Khi thừa kế một giao diện, một
lớp đang khai báo sẽ thực thi những hàm nào đó. Chúng ta sẽ
minh họa về giao diện thông qua việc giới thiệu một giao diện
đã được Microsoft định nghĩa, System.IDisposable. IDisposable
chứa một phương thức Dispose() dùng để xoá mã.
public interface Idisposable
{
void Dispose();
}
-
Một giao diện thì không cho phép chứa các phương thức nạp
chồng.
-
Các thành phần bên trong một giao diện luôn luôn là public và
không thể khai báo virtual hay static.
-
Chú ý: Tên của giao diện thường phải có ký tự I đứng đầu để
nhận biết đó là một giao diện
Constructor
-Cú pháp khai báo một Constructor là : chúng ta khai báo một phương thức mà
cùng tên với lớp và không có kiểu trả về.
public class MyClass
{
public MyClass()
{
}
/ / Phần còn lại của định nghĩa lớp
•
Như trong c++ và java, bạn có thể không cần định nghĩa constructor trong
lớp của bạn nếu không cần thiết. Nếu bạn không định nghĩa một constructor
nào trong lớp của bạn thì trình biên dịch tạo một constructor mặc định để
khởi tạo một số giá trị mặc định như: gán chuỗi rỗng cho chuỗi, gán 0 cho
kiểu số, false cho kiểu bool.
Chú ý :+ khi bạn đã định nghĩa một constructor trong lớp của bạn thì trình biên
dịch sẽ không tự động tạo ra constructor mặc định.
+Nếu bạn định nghĩa một hay nhiều constructor private thì những lớp thừa
kế lớp của bạn sẽ không thể khởi tạo được. Do đó chúng ta phải cân nhắc
kỹ lưỡng khi định nghĩa bổ từ của một constructor
Constructortĩnh(static)
Chúng ta định nghĩa một constructor tĩnh để khởi tạo giá trị cho các biến tĩnh.
class MyClass
{
static MyClass()
{
/ / Khởi tạo mã
}
/ / Phần còn lại của định nghĩa lớp
}
- Một nguyên nhân để viết một constructor tĩnh là: Nếu lớp của bạn có một
số trường hay thuộc tính cần được khởi tạo từ bên ngoài trước khi lớp
được sử dụng lần đầu tiên
- Trong C#, Constructor tĩnh thường được thực hiện ngay trước lần gọi đầu
tiên của một thành viên trong lớp đó.
-cóthểGọicácconstructortừnhữngconstructorkhác
DestructorsvàphươngthứcDispose()
-C# cũng hỗ trợ Destructor, nhưng chúng không được dùng thường xuyên như trong C++ và cách
chúng hoạt động rất khác nhau. Bởi vì các đối tượng trong .NET và C# thì bị xoá bởi bộ thu
gom rác (garbage collection). Trong C#, mẫu destruction làm việc theo hai giai đoạn:
1.Lớp sẽ thực thi giao diện System.IDisposable, tức là thực thi phương thức IDisposable.Dispose().
Phương thức này được gọi tường minh khi trong đoạn mã khi một đối tượng không cần nữa.
2. Một Destructor có thể được định nghĩa và nó được tự động gọi khi đối tượng bị thu gom rác.
Destructor chỉ đóng vai trò như một máy rà soát lại trong một số trường hợp xấu client không
gọi phương thức Dispose().
Cú pháp của một Destructor giống như một phương thức nhưng có cùng tên với lớp, có tiền tố là
một dấu sóng(~), không có kiểu trả về, không có tham số truyền và không có bổ từ.
ThựcthiphươngthứcDispose()vàmộtDestructor
-Destrutor được gọi khi một đối tượng bị hủy. Có một vài điểm ta phải nhớ như
sau:
1. Chúng ta không thể biết trước khi nào một thể hiện bị huỹ, tức là ta không biết trước
khi nào một Destructor được gọi.
2. Bạn có thể tác động đến bộ thu gom rác để chạy tại một thời điểm trong đoạn mã của
bạn bằng cách gọi phương thức System.GC.Collect(). System.GC là một lớp cơ
sở .NET mô tả bộ thu gom rác và phương thức Collect() dùng để gọi bộ thu gom
rác.
3. Có một lời khuyên là chúng ta không nên thực thi một Destructor nếu như lớp của
bạn không thực sự cần đến nó. Nếu một đối tượng thực thi một Destructor, thì nó
đặt một đặc tính quan trọng vào quá trình thu gom rác của đối tượng đó. Nó sẽ trì
hoãn việc di chuyển cuối cùng của đối tượng từ bộ nhớ. Những đối tượng không có
một Destructor thì bị xoá khỏi bộ nhớ trong một lần hoạt động của bộ thu gom rác.
Còn đối tượng có Destructor thì nó sẽ qua hai bước : lần đầu nó gọi Destructor mà
không xoá đối tượng, lần thứ hai mới thực sự xoá đối tượng.
-Chú ý : Không có bất kỳ một tham số nào trong một Destructor, không kiểu trả về và
không có bổ từ. Không cần thiết phải gọi tường minh một Destructor của lớp cơ sở
mà trình biên dịch sẽ tự động sắp xếp tất cả Destructor được định nghĩa trong các
lớp thừa kế đều được gọi.
Cáctrườngchỉđọc(Readonlyfields)
- Hằng là một biến mà chứa một giá trị không thay đổi. Trong C# khái niệm
hằng cũng giống như mọi ngôn ngữ khác. C# hỗ trợ một kiểu biến khác có
lợi hơn trong trường hợp này là: các trường chỉ đọc.
- Từ khoá readonly thì linh động hơn từ khoá const.
-Bởi vì bạn có thể khởi tạo giá trị cho một trường chỉ đọc trong constructor.
Và nó cho phép một trường chỉ đọc là một thể hiện(instance) hay một
trường static có các giá trị khác nhau trong mỗi thể hiện của lớp đó. Nếu
bạn muốn một trường chỉ đọc là static thì bạn phải khai báo tường minh
Chú ý: trường chỉ đọc và nó không thể được gán giá trị bên ngoài constructor.
Struct
-Cú pháp để định nghĩa một struct được mô tả trong ví dụ sau:
struct Dimensions
{
public double Length;
public double Width;
}
1.Struct là một kiểu giá trị, không phải là kiểu tham khảo.
2. Struct không hổ trợ thừa kế.
3. Có vài sự khác nhau trong cách làm việc của các constructor đối với struct. Trình biên dịch luôn
luôn cung cấp một constructor không tham số mặc định, và không được cho phép thay thế.
4. Với một struct, bạn có thể chỉ rỏ cách mà các trường được đặt ngoài bộ nhớ
- Mặc dù struct là kiểu giá trị nhưng cú pháp để sử dụng nó giống như sử dụng lớp. Ví dụ như
bạn khai báo như trên thì bạn có thể viết như sau:
Dimensions point = new Dimensions();
point.Length = 3;
point.Width = 6;
Chú ý rằng struct là các kiểu giá trị, do đó thao tác new sẽ không làm việc theo cách của lớp hay
những kiểu tham khảo khác. Nó chỉ đơn giản định vị trên bộ nhớ và gọi constructor thích hợp
để khởi tạo các trường. Do đó bạn hoàn toàn có thể viết:
Dimensions point;
point.Length = 3;
point.Width = 6;
Nếu Dimensions là một lớp thì đoạn mã trên sẽ báo lỗi nhưng là một struct thì hoàn toàn hợp lý
Nạpchồngtoánhạng
-Một số trường hợp chúng ta nên viết các toán hạng nạp chồng:
1. Trong thế giới toán học, mọi đối tượng toán học như: tọa độ, vector, ma trận, hàm số và vân vân. Nếu bạn
viết chương trình làm những mô hình toán học hay vật lý, bạn nhất định sẽ mô tả những đối tượng này.
2.Những chương trình đồ hoạ sẽ sử dụng các đối tượng toán học và toạ độ khi tính toán vị trí của trên màn
hình.
3. Một lớp mô tả số lượng tiền.
4. Việc sử lý từ hay chương trình phân tích văn bản có lớp để mô tả các câu văn, mệnh đề và bạn phải sử dụng
các toán hạng để liên kết các câu lại với nhau.
Vidu:
Matrix a, b, c;
// assume a, b and c have been initialized
Matrix d = c * (a + b);
Có thể nap chồng : Matrix d = c.Multiply(a.Add(b));
ĐA HÌNH
VÍDỤ:
usingSystem;
publicclassDrawingObject
{publicvirtualvoidDraw(){
Console.WriteLine("agenI'mjustericdrawingobject.");
}
}
publicclassLine:DrawingObject
{publicoverridevoidDraw()
{
Console.WriteLine("I'mLine.");
}
}
publicclassCircle:DrawingObject
{publicoverridevoidDraw()
{
Console.WriteLine("I'mCircle.");
}
}
publicclassSquare:DrawingObject
{publicoverridevoidDraw()
{
Console.WriteLine("I'mSquare.");
}
}
publicclassDrawDemo
{publicstaticintMain()
{
DrawingObject[]dObj=newDrawingObject[4];
dObj[0]=newLine();
dObj[1]=newCircle();
dObj[2]=newSquare();
dObj[3]=newDrawingObject();foreach(DrawingObjectdrawObjindObj)
{drawObj.Draw();
}return0;
}
}
ĐÓNG GÓI
o ng go i trong class, giu p phân biêt gi a ca c đô i t ng kha c nhau, ́ ́ ́ ̃ ́ ́ ́Đ ̣ ư ượ
giu p ta i s dung trong 1 ch ng tri nh kha c ́ ́ ̀ ́ử ̣ ươ