In order to explain my problem here is an example
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 mObjec开发者_如何转开发t;
}
}
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;
}
}
}
}
My problem is that in Main() I don't know what type the returnMyObject() method returns so I can't send it to MyMethod. Is there a way to cast the objects ??
Because in your design of returnMyObject()
you went back to the most common object
references, you will have to find out in runtime:
if (obj1 is string)
myMethod((string)obj1); //--->cast it
else if (obj1 is DateTime)
myMethod((DateTime) obj1);
You could check the object's type at runtime:
public static void myMethod(Object o) { if (o is DateTime) myMethod((DateTime)o); else if (o is string) myMethod((string)o); }
Although in your case, you might just as well pass a myAbstarctClass
instance to myMethod
, and then call returnMyObject()
there.
You can either use dynamic feature from C# 4.0 or change design to utilize some kind of double dispatch technique
dynamic obj1 = mac1.returnMyObject();
dynamic obj2 = mac2.returnMyObject();
Use Polymorphism mechanisms so you don't need to know the type of object.
Make myMethod
an abstract method of myAbstarctClass
and provide implementations in both MyNewAbstractClass1
and MyNewAbstractClass2
.
Modify myAbstractClass1.returnMyObject()
to return myAbstarctClass
(not object
).
The test code in Main
can then be written:
...
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();
Edit: This can be further simplified, since the returnMyObject()
methods are no longer necessary - they just return the object you already have. The test code is now simply:
mac1.myMethod();
mac2.myMethod();
// etc...
Console.ReadKey();
No, you have to either create switch with all possibilities, or something like Dictionary<Type, Delegate>
or you can just make myMethod(object obj)
it's called Multiple dispatch (http://en.wikipedia.org/wiki/Multiple_dispatch) and there are some libraries that can do it
Since you seem to be using your class as a container for a type (eg. DateTime
, string
), perhaps Generics would a be better choice than Inheritance:
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;
}
}
}
精彩评论