抽象类实例化

4

我有一个基础的抽象类,有几个类继承并重写它,但它们都有相同的构造函数。目前,我通过switch语句调用每个构造函数:

case 1: return new A(arg1); // arg is int

等等,大约涉及10个类。有没有一种使用泛型或委托的方法,可以传入一个类名并使用参数实例化该类型?

这会有所帮助,因为如果我更改构造函数,我还必须更改每个实例。

委托是最直接的方法,但研究表明将构造函数分配给委托是不行的。

增加: 我现在使用的是笔记本电脑的wifi而不仅仅是手机,所以接下来是一些代码示例。

这是目前发生的情况的示例:

switch (new Random().Next(4))
{
    case 3:
         // classA : baseClass, args{int, bool, otherClass}
         return new classA(arg1, arg2, arg3);
    case 2:
         // classB : baseClass, args{int, bool, otherClass}
         return new classB(arg1, arg2, arg3);
    case 1:
         // classC : baseClass, args{int, bool, otherClass}
         return new classC(arg1, arg2, arg3);
    case 0:
         // classD : baseClass, args{int, bool, otherClass}
         return new classD(arg1, arg2, arg3);
    default:
         continue;
}

我希望在块的结尾处使用一个参数实例化器,并传入三个参数。

我想到的解决方案是创建一个类似于以下工作方式的实例化器类:

ClassInstantiator inst = new ClassInstantiator(arg1, arg2, arg3);
switch(new Random().Next(4))
{
     case 4:
         return inst.instantiate<classA>();
     ...
}

这是否已经内置于语言中?或者有没有更加优美的解决方案?

对于一个好问题,点赞! - Myles McDonnell
经过进一步思考,我意识到激活器是我部分描述的技术。 - jeubank12
4个回答

5
您无法逃避这样一个事实,即必须有某种条件来决定构建什么,但您可以封装它。我向您介绍最流行的GOF模式之一:http://en.wikipedia.org/wiki/Factory_method_pattern
例如:
public abstract class MyBase(string name){}
public class Concrete1 : MyBase{}
public class Concrete2 : MyBase{}

public class MyFactory
{
   public MyBase Create(Criteria criteria)
   {
       //conditional logic/reflection
   }
}

所以基本上你需要为每个想要实例化的类创建另一个类?...问题是这并不能让我避免为每个情况语句调用相同的参数。例如,我想将类名A存储在变量中,然后使用该变量调用方法来实例化具有共同参数的所需类。 - jeubank12
不,你只需要一个类来封装选择具体类型的单个方法,并返回基础类型。这要求你传递某些东西作为选择的标准。你提到了类型,你可以使用它(在这种情况下,反射可能是理想的@phoog),或者可能有另一个更具领域特定性的标准? - Myles McDonnell

5

你可以对泛型类型施加的唯一与构造函数相关的约束是new()约束,它要求具有公共无参构造函数。

你可以使用反射;该示例假设所有相关类型都有一个接受int参数的构造函数(如你的示例),并且抽象基类称为B

public T CreateInstance<T>(int i) where T : B
{
    return (T)Activator.CreateInstance(typeof(T), i);
}

然后你可以像这样调用它:
A a = CreateInstance<A>(3);

1
另外,请注意,如果您实际使用new()约束,则每当您使用new时,都会得到一个编译器生成的对Activator.CreateInstance的调用。 - Jeffrey Hantin

1
你可以创建一个字典,以类名为键,以构造函数委托为值。
Dictionary<string,Func<int,BaseClass>> _dict = new Dictionary<string,Func<int,BaseClass>>();
_dict.Add("ClassA", i => new ClassA(i));
_dict.Add("ClassB", i => new ClassB(i));

// Create ClassA object by class name
BaseClass obj = _dict["ClassA"](5);

0

我并不反对你的说法,但是你能进一步解释一下吗?这些容器是否可以根据构造函数参数类型实例化不同的具体类? - Myles McDonnell
1
@MylesMcDonnell 我理解这个问题的逻辑是基于除了构造函数参数类型之外的某些条件(我假设“它们都有相同的构造函数”意味着构造函数具有相同数量的参数和相同的类型)。 - phoog
是的,你说得对,我上面的评论在这个问题的背景下是无意义的。不过,我很想知道是否有任何容器可以根据参数的具体类型选择一个具体的实现?我认为可能有,并且泛型是实现的关键因素。 - Myles McDonnell
@Myles - 我相信是这样的。看起来StructureMap支持配置条件实例,但我没有使用过这个功能。 对于我的回答如此模糊,我感到抱歉。通常我喜欢提供一些例子,但目前无法做到。我将其发布为社区维基,以便其他人可以添加一些详细信息到这个答案中。 - Dr. Wily's Apprentice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接