开发者

Polymorphism and overloading with static methods in C#.

I have been trying to generate a Factory supposed to return a different object of a common interface (say Item) according to the input parameter (I call it a context) of the function getItem(A context)

Now, assume I define a new type of context: B which inherits from A.

I wanted to return a different item depending on whether the object passed to the factory was of class B or A.

I tried to do as follows (overloading the method):

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

This works fine if I do something like this:

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

However, if I cast and object to type A:

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

the first factory method is called.

I thought that polymorphism would ensure the execution开发者_运维百科 of the second method even after the cast, and I would like to know if I missed something?

I am aware that I could keep having a single method and use the is operator to check what the type of the variable is, but I thought the solution I presented above was a bit more elegant.


Overloading is decided at compile-time (aside from using dynamic typing in C# 4) based on the compile-time type of the arguments - and in your last snippet, the compile-time type of the argument is A, so it calls Factory.getItem(A).

Only virtual method calls are polymorphic (using overriding), where the actual execution-time type of the target object to decide which implementation to call. If it makes sense for A and B to have a virtual method (overridden in B) which can be called by Factory.getItem to handle the differences, that's great... otherwise you're stuck with either dynamic typing or something like is.


You can not achieve what you are pretending the way you have things set up right now.

One option is to have some logic in your factory methods that can distinguish the type of the argument. Clunky, not pretty, but it works:

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

Another option is to make the context objects responsible of creating the object. For example:

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 }
}

And now you could do:

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

No if you do the following:

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

ContextB.CreateItem() will be called.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜