Những chủ đề tiến bộ trong C#
Các ép kiểu do người dùng định
nghĩa – Phần 2
Ép kiu giữa lớp dẫn xuất và lớp cơ sở
Để xem làm thế nào vic ép kiểu này m, ta xem xét 2 lớp Mybase và
Myderived , trong đó Mydrived được dẫn xuất trực tiếp hoặc gián tiếp tlớp
sở
đầu tiên tlớp Myderived đến Mybase ; luôn luôn ( giả shàm dựng giá
trị)có thể viết :
MyDerived derivedObject = new MyDerived();
MyBase baseCopy = derivedObject;
Trong trường hợp này,chúng ta ép kiểu không tường minh từ myderived đến
mybase. điu này làm việc bởi vì luật là bt kì tham chiếu đến 1 kiểu mybase
được cho phép để chuyển thành đối tượng của lớp mybase hoặc đến đối
tượng bất kì được dẫn xuất từ lớp mybase.trong ngôn ngữ lập trình hướng
đối tượng, thể hiện của lớp dẫn xuất là thhiện của một lớp cơ sở cộng thêm
với một thứ gì đó thêm. tất cả chức năng và thuộc tính được định nghĩa trong
lớp cơ scũng được định nghĩa trong lớp dẫn xuất .
Bây giờ ta có thể viết
MyBase derivedObject = new MyDerived();
MyBase baseObject = new MyBase();
MyDerived derivedCopy1 = (MyDerived) derivedObject; // OK
MyDerived derivedCopy2 = (MyDerived) baseObject;
Tất cả c u lệnh trên hợp lệ trong C# và minh họa việc ép kiểu từ lớp
sở sang lớp dẫn xuất. tuy nhiên u lệnh cuối sẽ tung ra biệt lệ khi thực
thi.
Chú ý rng những lệnh ép kiểu mà trình biên dịch cung cấp , mà chuyn
giữa lớp svà lớp dẫn xuất thì không thực sự chuyển bất cứ dữ liu nào
trên các đối tượng.tất cchúng làm thiết lập một stham chiếu mới để
quy cho một đối tượng nếu hợp lcho việc chuyển đổi .những lệnh ép
kiểu này thì rất khác trong tự nhiên tnhững cái mà ta tng xuyên tđịnh
nghĩa.ví dụ, trong dSimplecurrency chúng ta định nghĩa việc ép kiểu là
chuyển giữa 1 kiểu tiền tệ sang kiểu số thực. trong ép kiểu thực-thành-
currency, chúng ta thực stạo một cu trúc currency mới và khi tạo với
giá trị được yêu cu .những lệnh ép kiểu tiền định nghĩa giữa những lớp cơ s
và lớp dẫn xuất không làm điều này.nếu ta thực sự chuyển 1 thể hiện
Mybase thành một đối tượng Myderived thực với giá trdựa trên ni dung
của thể hiện Mybase, ta sẽ không thể sdụng cú pháp ép kiểu để làm điều
này.tuchọn hợp nhất thường xuyên định nghĩa 1 hàm dng của lớp
dẫn xuất mà lấy thể hiện của lớp snhư 1 thông số và m dựng
này biu diễn việc khởi tạo chính xác:
class DerivedClass : BaseClass
{
public DerivedClass(BaseClass rhs)
{
// khởi tạo đối tượng từ thể hiện Base
}
// etc.
Ép kiu boxing và unboxing
Ví dvới cấu trúc currency:
Currency balance = new Currency(40,0);
object baseCopy = balance;
Khi ép kiểu không tường minh trên được thực hiện nội dung của balance
được sao chép o heap trong đối tượng box đi tượng basecopy tham
khảo đến đối tượng này.khi chúng ta định nghĩa cấu trúc currency , .net
framework cung cấp không tường minh một lp ( ẩn) khác , một lớp
currency boxed, chứa đựng tất cả các trường như cấu trúc currency
nhưng kiểu tham chiếu lưu trong heap.điều này xảy ra bất c khi nào
chúng ta định nghĩa một kiu dữ liệu- dù đó là struct hay kiểu liệt kê ( enum)
,và kiu tham khảo boxed tồn tại đáp ứng đến tất ckiểu dữ liu nguyên
thu int,double,uint, và ...ta không th truy nhập vào các lớp này nhưng
chúng slàm việc bất cứ khi nào việc ép kiểu thành đối tượng khi chúng
ta ép kiu currency thành đối tượng một thể hin currency boxed tạo ra và
khởi tạo với tất cả các giá trtừ cấu trúc currency. trong dụ trên basecopy
sẽ tham khảo đến lớp currency boxed.
Ép kiểu còn được biết đến như unboxing,dùng cho việc ép kiểu giữa
những lớp kiểu tham chiếu cơ svà kiu tham chiếu dẫn xuất.đó là ép kiểu
tường minh, bởi vì 1 biệt lệ s được tung ra nếu đối tượng được ép kiểu
không ép đúng.
object derivedObject = new Currency(40,0);
object baseObject = new object();
Currency derivedCopy1 = (Currency)derivedObject; // OK
Currency derivedCopy2 = (Currency)baseObject; // Exception thrown
Khi sdụng boxing unboxing điều quan trng để hiểu là c hai tiến trình
này thực sự sao chép dữ liệu vào một đối tượng boxed hay unboxed. chính
do đó, thao tác trên đối tượng hộp sẽ không tácđộng đến nội dung của
kiểu dữ liệu nguyên thuỷ.
Multiple casting
dvới cu trúc currency , giả sử trình biên dịch chạm tn với các dòng
mã sau:
Currency balance = new Currency(10,50);
long amount = (long)balance;
double amountD = balance;
Đầu tiên chúng ta khởi tạo 1 thể hiện currency ,sau đó ép thành kiểu
long.vấn đề ta chưa định nghĩa ép kiểu cho việc y. tuy nhiên đon mã
nay vẫn biên dịch thành công bi vì trình biên dịch nhận ra rằng ta đã định
nghĩa ép kiểu không tường minh để chuyển currency thành float.và nó biết
cách chuyển tường minh tfloat sang long. do đó, sbiên dịch đầu
tiên chuyển balance sang float rồi t float sang long.tương tự cho kiểu
double tuy nhiên do chuyn tfloat sang double không tường minh , do đó
chúng ta có thể viết lại tường minh :