2011-07-28 24 views
7

Tôi đã cố gắng để tạo ra một nhà máy phải trả về một đối tượng khác nhau của một giao diện chung (nói Item) theo thông số đầu vào (tôi gọi nó là một ngữ cảnh) của hàm getItem(A context)Đa hình và quá tải với các phương pháp tĩnh trong C#.

Bây giờ, giả sử tôi xác định một loại ngữ cảnh mới: B được kế thừa từ A.

Tôi muốn trả lại một mục khác tùy thuộc vào việc đối tượng được chuyển đến nhà máy có thuộc loại B hoặc A hay không.

tôi đã cố gắng để làm như sau (quá tải phương pháp):

class Factory 
{ 
    static Item getItem(A context) {...} 
    static Item getItem(B context) {...} 
} 

này hoạt động tốt nếu tôi làm điều gì đó như thế này:

B bContext=new B(); 
Item it=Factory.getItem(bContext); 

Tuy nhiên, nếu tôi đúc và đối tượng để gõ A :

A bContext=(A) new B(); 
Item it=Factory.getItem(bContext); 

phương pháp nhà máy đầu tiên được gọi.

Tôi nghĩ rằng đa hình sẽ đảm bảo thực hiện phương pháp thứ hai ngay cả sau khi diễn viên, và tôi muốn biết nếu tôi bỏ lỡ một cái gì đó?

Tôi biết rằng tôi có thể tiếp tục có một phương pháp duy nhất và sử dụng toán tử is để kiểm tra loại biến là gì, nhưng tôi nghĩ giải pháp tôi đã trình bày ở trên là thanh lịch hơn một chút.

Trả lời

10

quá tải được quyết định tại thời gian biên dịch (ngoài việc sử dụng gõ năng động trong C 4 #) dựa trên loại thời gian biên dịch của các đối số - và trong đoạn cuối cùng của bạn, loại thời gian biên dịch của các đối số là A , do đó, nó gọi Factory.getItem(A).

Chỉ các cuộc gọi phương thức ảo có tính đa hình (sử dụng ghi đè), nơi loại thời gian thực hiện thực tế của đối tượng đích để quyết định thực hiện cuộc gọi nào. Nếu có ý nghĩa đối với AB để có phương thức ảo (được ghi đè trong B) có thể được gọi bằng Factory.getItem để xử lý sự khác biệt, điều đó thật tuyệt ... nếu không bạn bị kẹt với gõ động hoặc một cái gì đó như is.

1

Bạn không thể đạt được những gì bạn đang giả vờ cách bạn thiết lập mọi thứ ngay bây giờ.

Một tùy chọn là có một số logic trong các phương pháp nhà máy của bạn có thể phân biệt loại đối số. Clunky, không đẹp, nhưng nó hoạt động:

class Factory 
{ 
    static Item getItem(ContextA context) 
    { 
     if (context is ContextB) {...} 
     else {...} 
    } 
} 

Một tùy chọn khác là làm cho đối tượng bối cảnh chịu trách nhiệm tạo đối tượng.Ví dụ:

public class ContextA 
{ 
    .... 
    internal virtual Item CreateItem() { //specific creation logic for ContextA } 
} 

public class ContextB: ContextA 
{ 
    .... 
    internal override Item CreateItem() { //specific creation logic for ContextB } 
} 

Và bây giờ bạn có thể làm:

class Factory 
{ 
    static Item getItem(ContextA context) 
    { 
     return context.CreateItem(); 
    } 
} 

Không nếu bạn làm như sau:

ContextA context = new ContextB(); 
Item item = Factory.getItem(context) 

ContextB.CreateItem() sẽ được gọi.

Các vấn đề liên quan