【问题标题】:Require a child of an abstract class in method arguments在方法参数中需要一个抽象类的子类
【发布时间】:2018-04-26 20:38:34
【问题描述】:

我有一个获取 SubForm 对象并显示它的方法。

public void subFormLauncher(object sender, SubForm f)
{
    if (f == null)
    {
        f = new SubForm(this);    // This line is problematic
        f.Show();
    }
    else
    {
        if (!f.Visible)
        {
            f.Show();
        }
        f.Activate();
    }
}

VS 很生气,因为 SubForm 是一个抽象类,而我不小心实例化了它的一个实例(公平)。

public abstract class SubForm : Form
{
    public SubForm(frmMain f) { }
    public abstract void InitForm();
}

有没有办法在 subFormLauncher 的参数中指定我想要 SubForm 的子级?比如:

public void subFormLauncher(object sender, <T> extends SubForm f)

【问题讨论】:

    标签: c# oop abstract-class


    【解决方案1】:
    public void subFormLauncher(object sender, SubForm f)
    

    已经声明传入的对象必须是“SubForm”类型,问题是你的逻辑试图在这里新建一个子表单:

    f = new SubForm(this);    // This line is problematic
    

    但是作为它的抽象,你不能新的。如果您删除它,并且在传递给您的方法时不允许子表单为空,那么问题就解决了。

    【讨论】:

      【解决方案2】:

      你的整个方法似乎“不正常”:

      public void subFormLauncher(object sender, SubForm f) 让我想起了一个事件(对象发送者),但这看起来不像是一个事件。

      您将表单作为参数传递也很奇怪,更不用说您在其上所做的工作了。如果你给它,你就是把它放到前台,但如果不是你实例化它?

      你很有可能在XY problem这里很深。

      您将无法指定您想要创建的确切类型。一种方法可能是在混合中添加一些通用的:

      public void subFormLauncher<T>(object sender, T f) where T : SubForm 
      {
          if (f == null)
          {
              f = new T(this);    // This line is problematic
              f.Show();
          }
          else
          {
              if (!f.Visible)
              {
                  f.Show();
              }
              f.Activate();
          }
      }
      

      【讨论】:

      • 您缺少该类型的 new() 约束。此外,您没有使用默认构造函数。所以这显然不会编译。
      • @gnud 是对的。用f = (T)Activator.CreateInstance(typeof(T), new object[] { this }); 替换构造函数将解决这个问题。但是您关于事件处理程序的观点是正确的。我想提供一个默认方法来显示任何给定的表单。
      • 我不太明白你想告诉我什么。 public SubForm(frmMain f) 是一个有效的构造函数。如果构造函数不太可能工作(因为每个孩子可能有也可能没有),FactoryMethod 可能是要走的路。
      • 或者只是new T(); T.Parent = this;。为什么复杂?
      • @gnud:假设 Parent 是公共字段/不是只读属性。构造函数输入通常用于不应公开设置/设置一次以上的值。当然,如果这是真的,那么赋值是最简单的方法。
      【解决方案3】:

      你可以使用一个接口并在你的方法调用中请求这个。

      【讨论】:

      • 这有什么帮助?
      • 我不能使用接口,因为我需要继承Form,它是一个类
      • 我明白了。我正在考虑向抽象类添加一个接口。但是,正如 gmn 所示,这又是不需要的。 gmn的回答应该没问题...
      猜你喜欢
      • 2021-06-03
      • 2021-06-11
      • 2010-12-13
      • 1970-01-01
      • 2015-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多