4

我需要在我的项目中有多个表单类。所以考虑将这些形式共有的所有东西放在抽象类中。该类将具有继承的 Form 类和一个接口。像这样:

public interface IMyForm
{
void Init();
}

public abstract class AMyForm : Form, IMyForm
{
    void IBrowser.Init()
    {
        throw new NotImplementedException();
    }     
}

public partial class MainClass : AMyForm 
{

// But here the warning is shown (That i have to add override keyword),
// but when i do, The error is shown that i cannot override from non abstract thing 
    public void Init() 
    {
    }
}

你能告诉我如何实现吗?

4

3 回答 3

8

虽然 Jon Skeets的回答对于一般编程来说是正确的,但我建议不要在表单和用户控件上使用抽象类。第一个问题是,该设计器将无法创建抽象类的实例,因此将无法在设计器中显示抽象表单继承的表单。这意味着您将无法通过设计器向表单添加新控件,除非- 正如下面评论中所建议的那样 - 您添加一个实现抽象类的代理类,然后用作其他继承表单的基础,例如:AbstractMyForm -> MyFormSurrogate -> MyForm.

在我看来,第二个也是更大的问题是,这意味着您正试图将逻辑融入表单。这通常是不希望的,尤其是当您最终将业务逻辑与显示技术耦合时,在这种情况下Winforms。我的建议是尝试使用Model View Presenter 模式在普通类(使用抽象类、接口等)中分离尽可能多的逻辑,然后将它们数据绑定到表单。如果有共享的可视部分(例如:一组复选框),请为这些部分制作用户控件,然后在表单上重用它们。

我希望我没有过多地假设您对使用 winforms 的了解太多,但是当我开始从事 GUI 开发时,我也有类似的问题。

于 2012-07-16T20:53:04.783 回答
7

您只想不在抽象类中使用显式接口实现:

public abstract class AMyForm : Form, IMyForm
{
    public virtual void Init()
    {
        throw new NotImplementedException();
    }     
}

或者只是使其抽象:

public abstract class AMyForm : Form, IMyForm
{
    public abstract void Init();
}

在这两种情况下,您只需在具体类中覆盖它。

或者,如果你真的想在你的抽象类中使用显式接口实现,你应该在你的具体类中再次使用它:

public partial class MainClass : AMyForm, IMyForm
{
    void IMyForm.Init() 
    {
        // Stuff
    }
}

缺点是任何AMyForm这样做的子类基本上都会有损坏的实现。在这里使用第一种方法更好。IMyForm

编辑:或者,根据 supercat 的建议:

public abstract class AMyForm : Form, IMyForm
{
    void IBrowser.Init()
    {
        InitImpl();
        // And anything else you need...
    }     

    // Or abstract...
    protected virtual void InitImpl()
    {
    }
}

然后InitImpl在你的具体类中覆盖。

于 2012-07-16T16:09:10.457 回答
3

抽象类未在设计视图中显示;您可以通过在抽象类中添加编译器 if 语句以使其在设计时不抽象来解决它。

#if RELEASE
    public abstract class AbstractForm : Form, IInterface
#else
    public class AbstractForm : Form, IInterface
#endif
    {
        // Your abstract code here.
    }

这是一个很好的小技巧,非常有效。您可以使用相同的技巧在设计时和运行时之间切换虚拟方法和抽象方法。

附录:

应该注意的是,不需要使用抽象形式。从非抽象形式继承更有效,并且产生的潜在问题更少。

public partial class Screen : Form, IInterface
{
    // Base Class here, complete with .designer.cs and .resx
    public Screen()
    {
        InitialiseComponent();
    }

    #region IInterface imported methods
    public partial void SomeMethod()
    {
        // Do something.
    }
    #endregion
}

然后,如果您想创建一个登录屏幕,例如:

public partial class LogonScreen : Screen, IInterface
{
    // Derived Class here, complete with .designer.cs and .resx
    public Screen()
    {
        InitialiseComponent();
    }

    #region IInterface imported methods
    public partial void SomeMethod()
    {
        // Do more somethings!
    }
    #endregion
}
于 2013-01-29T01:46:36.903 回答