多态性和铸造问题

时间:2010-08-05 12:15:51

标签: c# polymorphism abstract-methods abstract-class

为了解释我的问题,这里有一个例子

namespace CheckAbstarct
{

class Program
{
    static void Main(string[] args)
    {
        myAbstarctClass mac1 = ObjectFactory.ObjectCreator("aaa");
        myAbstarctClass mac2 = ObjectFactory.ObjectCreator("bbb");
        mac1.changeMyString();
        mac2.changeMyString();
        string myString = (string)mac2.returnMyObject();
        DateTime myObject = (DateTime) mac1.returnMyObject();

        object obj1 = mac1.returnMyObject();
        object obj2 = mac2.returnMyObject();

        myMethod(obj1);  //---> This is not compiling
        myMethod(obj2);  //---> This is not compiling

        myMethod(myString);  //---> works fine
        myMethod(myObject);  //---> works fine

        Console.ReadKey();
    }
    public static void myMethod(DateTime dt)
    {
    }
    public static void myMethod(string st)
    {
    }
}
abstract class myAbstarctClass
{
    protected string mMyString;
    public myAbstarctClass()
    {
        mMyString = "myAbstarctClass ";
    }
    public abstract void changeMyString();
    public abstract object returnMyObject();        
}

class MyNewAbstractClass1 : myAbstarctClass
{
    DateTime mObject;
    public MyNewAbstractClass1(string myString)
    {
        mMyString = myString;
        mObject = new DateTime().Date;
    }
    public override void changeMyString()
    {
        mMyString += " MyNewAbstractClass1";
        Console.WriteLine(mMyString);
    }
    public override object returnMyObject()
    {
        return mObject;
    }
}

class MyNewAbstractClass2 : myAbstarctClass
{
    string mString;
    public MyNewAbstractClass2(string myString)
    {
        mMyString = myString;
        mString = mMyString;
    }
    public override void changeMyString()
    {
        mMyString += " MyNewAbstractClass2";
        Console.WriteLine(mMyString);
    }
    public override object returnMyObject()
    {
        return mString;
    }
}

static class ObjectFactory
{
    public static myAbstarctClass ObjectCreator(string myString)
    {
        switch (myString)
        {
            case "aaa":
                return new MyNewAbstractClass1(myString);
            case "bbb":
                return new MyNewAbstractClass2(myString);
            default:
                return null;
        }
    }
}    
}

我的问题是在Main()中我不知道returnMyObject()方法返回什么类型,所以我无法将它发送给MyMethod。有没有办法摆放对象??

6 个答案:

答案 0 :(得分:5)

因为在您的returnMyObject()设计中,您回到了最常见的object引用,您必须在运行时找到它们:

if (obj1 is string)
     myMethod((string)obj1);  //--->cast it 
else if (obj1 is DateTime)
     myMethod((DateTime) obj1);

答案 1 :(得分:4)

您可以在运行时检查对象的类型:

public static void myMethod(Object o)
{
    if (o is DateTime)
        myMethod((DateTime)o);
    else if (o is string)
        myMethod((string)o);
}

虽然在您的情况下,您也可以将myAbstarctClass实例传递给myMethod,然后在那里拨打returnMyObject()

答案 2 :(得分:1)

您可以使用C#4.0中的动态功能或更改设计以使用某种双重调度技术

        dynamic obj1 = mac1.returnMyObject();
        dynamic obj2 = mac2.returnMyObject();

答案 3 :(得分:1)

使用多态机制,因此您无需知道对象的类型。

使myMethod成为myAbstarctClass的抽象方法,并在MyNewAbstractClass1MyNewAbstractClass2中提供实施。

修改myAbstractClass1.returnMyObject()以返回myAbstarctClass(不是object)。

然后可以编写Main中的测试代码:

...
myAbstarctClass obj1 = mac1.returnMyObject();
myAbstarctClass obj2 = mac2.returnMyObject();

obj1.myMethod();        // calls MyNewAbstractClass1.myMethod()
                        // no if statement required!

obj2.myMethod();        // calls MyNewAbstractClass2.myMethod()
                        // no if statement required!

Console.ReadKey();

编辑:这可以进一步简化,因为不再需要returnMyObject()方法 - 它们只返回您已有的对象。测试代码现在只是:

mac1.myMethod();
mac2.myMethod();

// etc...
Console.ReadKey();

答案 4 :(得分:0)

不,您必须创建具有所有可能性的开关,或类似Dictionary<Type, Delegate>

之类的东西

或者你可以创建myMethod(object obj)

它被称为多次发送(http://en.wikipedia.org/wiki/Multiple_dispatch),并且有一些库可以做到这一点

答案 5 :(得分:0)

由于您似乎将您的类用作类型的容器(例如。DateTimestring),因此Generics可能是比继承更好的选择:

namespace CheckAbstract
{
    class Program
    {
        static void Main(string[] args)
        {
            myTemplateClass<DateTime> mac1 = new myTemplateClass<DateTime>(new DateTime().Date);
            myTemplateClass<string> mac2 = new myTemplateClass<string>("cat dog");

            mac1.changeMyString();
            mac2.changeMyString();
            string myString = (string)mac2.returnMyObject();
            DateTime myObject = (DateTime) mac1.returnMyObject();

            myMethod<string>(myString);
            myMethod<DateTime>(myObject);

            Console.ReadKey();
        }

        public static void myMethod<T>(T obj)
        {
        }
    }

    class myTemplateClass<T>
    {
        T mObject;
        string mMyString;
        public myTemplateClass(T init)
        {
            mMyString = init.ToString();
            mObject = init;
        }
        public void changeMyString()
        {
            mMyString += " " + mObject.ToString();
            Console.WriteLine(mMyString);
        }
        public T returnMyObject()
        {
            return mObject;
        }
    }
}
相关问题