C#表继承Abstract类并实现接口。

时间:2012-07-16 16:07:52

标签: c# winforms interface abstract-class

我需要在我的项目中有多个Form类。因此,考虑将这些形式的所有内容放在一起,在抽象课程中。该类将具有继承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() 
    {
    }
}

你能告诉我如何实现这个目标吗?

3 个答案:

答案 0 :(得分:7)

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

在我看来,第二个也是更大的问题,这意味着你试图将逻辑粘贴到表格中。这通常不是 ,特别是如果您最终将业务逻辑与显示技术相结合,在这种情况下Winforms。我的建议是尝试使用Model View Presenter pattern在普通类中使用尽可能多的逻辑(使用抽象类,接口等),然后data bind将它们分离到表单中。如果存在共享的可视部分(例如:一组复选框),请对这些部分进行用户控制,并在表单上重复使用它们。

我希望我没有过多地介绍你使用winforms的知识,但是当我开始进行GUI开发时,我遇到了类似的问题。

答案 1 :(得分:6)

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

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

答案 2 :(得分:3)

抽象类没有在设计视图中显示;你可以通过在抽象类中添加编译器if 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
}