【发布时间】:2016-12-22 23:59:19
【问题描述】:
我的目标是向客户端隐藏我正在构建的类的所有细节,包括要实例化的具体类。
客户端将枚举传递给工厂,该工厂返回适当派生类的实例,如下所示:
IAutomobile auto = Autofactory.GetAuto(param);
我创建了一个基类来完成大部分工作,但我需要特定的派生类来实现特定的逻辑。
public interface IAutomobile
{
void Rename(string p1, int p2);
}
public abstract class Automobile : IAutomobile
{
// Lots of properties and methods...
public abstract void Rename(string p1, int p2);
}
public class Jeep : Automobile
{
public override void Rename(string p1, int p2)
{
// Uses p1 & p2 with the base class
}
}
现在客户端可以调用:
auto.Rename("s1", "s2");
一切都很好,直到我创建了另一个派生类,它实现了具有不同签名的“Rename()”方法。
public class Audi : Automobile
{
public override void Rename(int i, SomeOtherClass someOtherClass)
{
//Does something with params
}
}
第二个实现有一个不同的签名,这并不奇怪会引发编译错误。
所以,我尝试使用这样的字典使参数传递更加“灵活”:
public interface IAutomobile
{
void Rename(Dictionary<object, object> parameters);
}
客户:
public class client
{
public void Client()
{
var parameters = new Dictionary<object, object>();
IAutomobile auto = AutoFactory.GetFactory();
parameters.Add("Param1Name", "string1");
parameters.Add("Param2Name", 21);
auto.Rename(parameters);
}
}
派生类:
public class Audi : Automobile, IAutomobile
{
public override void Rename(Dictionary<object, object> parameters)
{
// cast/box/unbox from dictionary objects...
// does something unique for Audis...
}
}
这就是我使用字典实现它的方式,其中参数是键/值对,但这似乎糟糕。我不明白它是如何给我买任何东西的。
或者,我可以创建代表所有派生类参数联合的对象,但同样,这看起来很糟糕。
有人可以建议我安排这种方式,以便不需要铸造、装箱和拆箱吗?
我不介意将要与 Rename() 方法一起使用的对象公开,例如:
auto.Rename(AudiFeatures);
或
auto.Rename(JeepFeatures);
(顺便说一句,我真的不想传递单个参数,我想传递对象)
这样的客户端调用不会起作用,因为我必须在客户端代码中硬编码类型。我想在工厂中对其进行硬编码,但是我将如何返回正确的接口类型,以及工厂的返回类型是什么?
我不想这样做:
IAutomobile<JeepRenamingData> auto = Autofactory.GetAuto<JeepRenamingData>(param);
我想这样做:
IAutomobile auto = Autofactory.GetAuto(param);
auto.Rename(myJeepRenamingData);
并让工厂返回正确的类型:
public static IAuto GetAutomobileManager(AutoMaker manufacturer)
{
switch (manufacturer)
{
case AutoMaker.Jeep
return new Jeep<JeepNamingOptions>();
case AutoMaker.Audi
return new Audi<AudiNamingOptions>();
}
}
【问题讨论】:
-
说我这样做:
IAutomobile auto = Autofactory.GetAuto(param);。我不知道auto是什么,那我怎么知道我应该传入AudiFeatures还是JeepFeatures?如果我确实知道auto是什么,那么转换到接口和/或使用工厂有什么意义?如果Rename更改了签名,则很好地表明它不适合覆盖方法的用例。 -
如果用户确实知道要调用哪种类型的重命名,那么您可以创建一个具有不同签名的重命名函数。当然,用户必须将汽车转换为具体的类才能调用它。但是无论如何都需要知道什么样的汽车,才能知道要调用什么样的重命名,不是吗?
-
@Chris Berger,这组类支持 UI。该示例旨在为您省去所有血淋淋的细节;)但基本上用户指示基础汽车是奥迪或吉普,并且该选择的回调可以确定哪辆车。因此,它会被知道......我不想让 UI 知道派生类的细节......
标签: c# oop generics inheritance