Câu lạc bộ Khoa học - THPT Chuyên Hồng Phong TPHCM LHPSC
Lập trình C# - Phần 4: C# Nâng cao Trang 1
Lập tnh C#
Dịch từ cuốn sách Beginning C Sharp Game Programming
Phần 4: C# Nâng cao
Không gian tên (Namespace)
Không gian tênmột định nghĩa mới trong ngôn ngữ máy tính, nhưng chúng rất hữu dụng, và một số
thể chứng minh rằng sự tồn tại của chúng là cần thiết.
Một trong những vấn đ lớn nhất của lập trình là quá tải tên (name overlapping). Hãy nói bạn tạo một
rừng các lớp cho chương trình của bạn, và sau đó bạn muốn nhập thư viện của một người nào khác đ
giúp cho chương trình của bạn. Điều gì s xảy ra nếu một slớp của người đó có cùng tên với các lớp
của bạn, nhưng làm các việc khác nhau? Thật không may, điều đó xảy ra rất nhiều.
Lấy dụ, cả Direct3D DirectSound đều các lớp tên Device, bạn ràng không thể có
hai lớp có cùng tên. Không gian tên m trnên đơn giản, vậy bạn thể ám chỉ c thiết bị
khác nhau như Direct3D.DeviceDirectSound.Device.
Bạn có thể nghĩ không gian tên giống như một thành ph. Nếu bạn chỉ nói với một người nào đó rằng
bạn sống đường Nguyễn Văn Cừ (chẳng hn), thì có đến hàng ngàn đường Nguyễn Văn Cừ trong
đất nước. Nếu muốn xác định chính xác bạn sống ở đâu, bạn cần phải nói với người đó cả thành phố
bạn sống nữa. Tạo ra một không gian tên giống như việc cụ thể thành phố và đường của bạn mà trong
đóbạn thể đặt một số lớp (đường ) bên trong một không gian tên c định (thành phố), do đó
chương trình của bạn sẽ được phân chia gọn gàng hơn.
Bạn có thể cho hầu như mọi thứ vào một không gian tên, bao gồm lớp, cấu trúc, trích xuất và cả một
không gian tên khác! Hình 4.1 cho thấy một dụ về không gian tên.
Hình 4. 1 Đây hai kng gian tên, System Chapter04. Trong các không gian tên các không
gian tên con và các lớp.
Không gian tên System Không gian tên Chapter04
Không gian tên
System.Data
Không gian tên
System.Collections
Lớp
System.Console
Lớp
Chapter04.Spacesation
Lớp
Chapter04.Spaceship
Câu lạc bộ Khoa học - THPT Chuyên Hồng Phong TPHCM LHPSC
Lập trình C# - Phần 4: C# Nâng cao Trang 2
Không gian tên rất tuyt bởi bạn thể phân cấp chúng bạn có thể cho nhiều không gian tên vào
một không gian tên đang tồn tại. Ví dụ, .NET framework bắt đầu với không gian tên System, với các
không gian tên khác trong nó, như là System.Data hay System.Collections.
Không gian tên phần cấp cho phép bạn tạo cả nhng hệ thống phân cấp lớn hơn, giống như Việt Nam
tồn tại Đông Nam Á, Thành phố HChí Minh tồn tại trong Việt Nam, đường Nguyễn Văn Cừ
tồn tại ở Thành phố Hồ Chí Minh.
Tạo Không gian tên
Đây là một số mã mô tả việt sử dụng một không gian tên:
namespace Chapter04
{
class Spaceship
{
// Mã đây
};
class Spacestation
{
// Mã đây
};
}
Và sau đó, ở bên ngoài không gian tên, bạn sẽ truy cập các lớp đó như thế này:
Chapter04.Spaceship s = new Chapter04.Spaceship();
Một tính năng khác của không gian tên chúng thể được phân chia thành nhiều phần. dụ, bạn
thể có mã như thế này trong một tập tin:
namespace Chapter04
{
class Spaceship
// blah blah
}
và sau đó cho một trạm không gian vào một tập tin khác:
namespace Chapter04
{
class Spacestation
// blah blah
}
Trình dịch C# sẽ tđộng ghép các không gian tên cho bạn, vậy bạn không phải cho tất cả vào một
tập tin lớn.
Sử dụng Không gian tên
Khi bạn đang ở trong một không gian tên, bạn có thể sdụng tất cả những gì trong không gian tên đó
mà không cần phải định danh . Nếu bạn muốn truy cập lớp Spaceship bên trong lớp
Spacestation trong dụ trước tôi cho bạn thấy, thì bạn chỉ cần đánh vào SpaceshipC# sẽ
cho rằng bạn đang nói đến Chapter04.Spaceship bởi vì bạn đang ở trong cùng không gian tên.
Tuy nhiên, nếu bạn đang ngoài không gian tên, bạn phải định danh không gian tên bằng cách
Chapter04. phía trước.
Câu lạc bộ Khoa học - THPT Chuyên Hồng Phong TPHCM LHPSC
Lập trình C# - Phần 4: C# Nâng cao Trang 3
Đương nhiên, Chapter04.Spaceship nhiều lần có thể gây phiền toái một lúc, đặc biệt bạn
biết rằng bạn chỉ sử dụng Spaceship trong Chapter04 chứ không phải nơi nào khác. May mn
thay, bạn được phép nói cho trình dịch C# rằng bạn muốn sử dụng tất cả những trong không gian
tên đó, bằng cách sử dụng từ khóa using. Sử dụng nó như thế này:
// phía trên ca mã ngun:
using Chapter04;
// phía sau trong tp tin:
Spaceship s = new Spaceship();
Ghi chú
Từ khóa using có thể được đặt ở mt số nơi. Từ khóa không thể được đặt trong một lớp, cấu
trúc hay trích xuất, nhưng thể đặt gần nmọi chỗ khác. Thực tế thì thường
được đặt đầu tập tin nguồn, vậy bạn sẽ biết những thư viện nào bạn cần ngay tức
thì.
Bí danh của Không gian tên
Không gian tên phân cấp thể gây phiền toái. Có thể bạn chưa thấy điều đó, nhưng khi bạn đi sâu
vào lập trình DirectX, bạn sẽ hét lên “Microsoft chết tiệt!” ở torng cổ họng của bạn… trừ khi bạn biết
vềdanh cho không gian tên.
Mọi thứ liên quan đến Direct3D đều bên trong không gian tên
Microsoft.DirectX.Direct3D. Vậy nếu bạn muốn truy cập một thiết bị Direct3D, bạn sẽ
phải Microsoft.DirectX.Direct3D.Device, đúng không? Thật may mắn, đặt danh
cho không gian tên slàm mọi thứ tốt hơn! Về cơ bạn, bạn thể lấy một không gian tên i với
C# cho nó một bí danh.
Đây là một bí danh cho không gian tên Direct3D:
using D3D = Microsoft.DirectX.Direct3D;
D3D.Device d; // thay cho: Microsoft.DirectX.Direct3D.Device d;
Hãy xem, đặt bí danh cho không tên gian làm mọi thứ đơn giản như thếo?
Tính đa hình (Polymorphism)
Chủ đề về tính đa hình rất là rộng và phức tạp – các trường đại học thường mở cả khóa hc về chđ
này. Tôi có thể cho bạn cái nhìn thoáng qua về chủ đề này. Nhưng sao bạn cũng không cần phải
học bất cứ quá phức tạp v tính đa hình.
Về ngôn ngữ, cái từ đa hình nghĩa là “nhiều dạng”. Trong ngôn ngữ máy tính, tính đa hình cho phép
bạn tương tác với nhiều đối tượng khác nhau mà không cần lo về việc những đối tượng này thực sự
gì.
Đâu là mt ví dụ đời thực của tính đa hình theo nghĩa của ngôn ngữ máy tính, hãy nghĩa về một cái xe
hơi. Bạn o một chiếc xe, mở lên, đạp chân ga, bạn biết điều sxảy ra: Chiếc xe bắt đầu
chy! Bây giờ ra khỏi chiếc xe đó, vào một chiếc xa hoàn toàn khác, m tương tự: Chiếc xe đó
cũng bắt đầu chạy! hai chiếc xa đều có chung giao diện (interface), và bạn thực sự không cần quan
tâm m sao động hoạt động ở bên dưới. Cho bạn đang lái một cái xe bốn xi lanh bình thường,
một chiếc xe đua tám xi lanh, hay một chiếc xa hơi điện, bạn biết rằng khi đạp ga, chiếc xe bắt đầu
Câu lạc bộ Khoa học - THPT Chuyên Hồng Phong TPHCM LHPSC
Lập trình C# - Phần 4: C# Nâng cao Trang 4
chy. Đây là ví dụ tốt nhất cho tính đa hình. Máy vi tính gọi một đối tượng làm việc, và đối tượng đó,
không quan tâm nó là gì, sm việc.
Đa hình cơ bản
Hãy nói bạn một cây phân cấp rất cơ bản: một gốc hai con. Gốc Spaceship (tàu vũ trụ)
các conCombatShip (tàu chiến) và CargoShip (tàu chở hàng), như hình 4.2.
Hình 4. 2 Một cây phân cấp đơn giản
Bạn có thể chơi với chúng như bình thường bạn vẫn làm:
Spaceship s = new Spaceship();
CargoShip c = new CargoShip();
Đương nhiên, không có mới. Nhưng điều đặc biệt một CargoShip mt Spaceship cho
phép bạn thực hiện một vài thủ thuật. Nhìn dòng mã này:
Spaceship s = new CargoShip();
Đoạn mã đó hoàn toàn hợp lệ. sao, một CargoShip mt SpaceShip, vậy snghĩa
khi làm một Spaceship trỏ tham chiếu tới một CargoShip, đúng không?
một giới hạn cho điều này: Tham chiếu SpaceShip sẽ không cho phép truy cập những phần
riêng nào trong lớp CargoShip mà nó không thừa kế từ SpaceShip. Giả sử rằng SpaceShip
hàm Refuel, và CargoShip hàm LoadCargo, thì hãy nhìn vào đoạn mã ví dụ sau:
Spaceship s = new CargoShip();
s.Refuel(); // ok
// s.LoadCargo(); // LI BIÊN DCH. SpaceShip không được LoadCargo
CargoShip c = (CargoShip)s; // vì vy, chuyn nó thành CargoShip
c.LoadCargo(); // ok
Câu lạc bộ Khoa học - THPT Chuyên Hồng Phong TPHCM LHPSC
Lập trình C# - Phần 4: C# Nâng cao Trang 5
Bất kể khi nào mà bạn một tham chiếu đến một lớp, bạn chỉ có thể truy cập vào nhng tính năng
của lớp xác định, bất kể nếu đối tượng thực sự có thể hỗ trợ nhiều tính năng hơn nữa.
Ghi chú
Ghi chú rằng bạn không thể sử dụng tính đa hình theo chiều ngược lại. Nếu bạn cố gắng viết
CargoShip c = new SpaceShip();, bạn sẽ có một lỗi biên dịch. Một SpaceShip không
phải là một CargoShip.
Hàm ảo (Virtual Function)
Một trong những khía cạnh quan trọng nhất của tính đa hình là ý tưởng về một m ảo. Một hàm ảo
cơ bản cho pp bạn định nghĩa một hàm trong lớp c sau đó có thể thay đổi . Hãy nói như thế
này, mọi u vũ trụ lo việc bị bắn bởi laser một cách khác nhau, vậy bạn định nghĩa việc x việc
đó trong lớp SpaceShip gốc. Sau đó, bạn đề nghị rằng tàu chiến thể lo việc bị trúng đạn một
cách khác bởi vì chúng có giáp tốt hơn.
Hàm ảo cho phép bạn giải quyết tình huống này mt cách dễ dàng, như bạn s thấy trong những mục
sau.
Khi không có Hàm ảo
Đây là một số mã sẽ làm rõ cái gì sẽ xảy ra trong dụ của tôi mà không có hàmo:
class Spaceship
{
public void LaserHit()
{
// Thit hi nhiu
}
}
class CombatShip : Spaceship
{
public void LaserHit()
{
// Thit hi ít
}
}
Điều mà tôi vừa m tạo một lớp SpaceShip mặc định làm cho u bnhiều thiệt hại khi bị
trúng laser. Tôi muốn CombatShip sẽ bị thiệt hại ít hơn bởi chúng có nhiều giáp hơn, vậy tôi
tạo một hàm LaserHit mới thực hiện thiệt hại ít hơn.
Đoạn mã làm chính xác những bạn nghĩ là:
Spaceship s = new Spaceship();
CombatShip c = new CombatShip();
s.LaserHit(); // Thit hi nhiu
c.LaserHit(); // Thit hi ít
Không có thủ thuật gì ở đây. Nhưng về các mã này thì sao?
Spaceship s = new Spaceship();
Spaceship c = new CombatShip();
s.LaserHit(); // Thit hi nhiu
c.LaserHit(); // Thit hi nhiu... ti sao?