C# Form that inherit Abstract class AND implements interface.

12,198

Solution 1

You just want to not use explicit interface implementation in your abstract class:

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

Or just make it abstract:

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

In both cases, you then just override it in your concrete class.

Alternatively, if you really want to use explicit interface implementation in your abstract class, you should use it again in your concrete class:

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

The downside is that any subclass of AMyForm which doesn't do this will basically have the broken IMyForm implementation. Using the first approach is better here.

EDIT: Or, as per supercat's suggestion:

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

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

Then override InitImpl in your concrete class.

Solution 2

While Jon Skeets answer is correct for general programming, I would advise AGAINST using abstract classes on Forms and User controls. First issue is, that designer won't be able to create an instance of the abstract class and thus will not be able to display a form that inherits FROM the abstract form in the designer. Meaning that you will not be able to add new controls to form via designer, unless - as suggested in comments below - you add a surrogate class that implements the abstract class and is then used as a base for other inherited forms, e.g.: AbstractMyForm -> MyFormSurrogate -> MyForm.

Second and larger issue is in my opinion, that this means that you are trying to stick logic into forms. This is usually not desired, especially if you end up coupling your business logic to your display technology, in this case Winforms. My advice would be to try to use the Model View Presenter pattern to separate as much logic as possible in ordinary classes (using abstract classes, interfaces, etc.) and then data bind them to the form. If there are visual parts that are shared (e.g.: a group of checkboxes), make user controls for such parts and just reuse them on forms.

I hope I didn't presume too much of your knowledge of working with winforms, but I had similar questions when I started getting into GUI development.

Solution 3

With abstract classes not showing in design view; you can get around it by adding a compiler if statement to the abstract class to make it not abstract at design time.

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

It's a nice little hack that works quite effectively. You can use the same trick to switch between virtual and abstract methods between design time and run time.

ADDENDUM:

It should be noted that using abstract forms is unneeded. It is more efficient and creates less potential problems to inherit from a non-abstract Form.

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
}

And then, if you wanted to create a Logon Screen for example:

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
}
Share:
12,198
Marshall
Author by

Marshall

Updated on June 04, 2022

Comments

  • Marshall
    Marshall almost 2 years

    I need to have a multiple Form classes in my project. So was thinking about putting everything those forms will have in common, together in abstract class. This class will have inheriet Form class and also an interface. Sth like that:

    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() 
        {
        }
    }
    

    Could u tell me how to achieve that ?

  • Marshall
    Marshall almost 12 years
    Hi, thx for replay. So, what is the best way to create application (avoiding bad coding practices ofc), that has multiple, similar Forms? I would like to do Interface (list of necessary methods), abstract class (some of method's default behaviors) and ofc concrete class, which has inherit Form class...
  • Jon Skeet
    Jon Skeet almost 12 years
    @Marshall: I haven't done enough GUI development to give a really good answer for that, but either of the approaches I've shown you should work...
  • supercat
    supercat almost 12 years
    If one wants to use explicit interface implementation, the proper approach is not to have derived classes re-derive the interface, but instead have a non-virtual explicit implementation which does nothing except call a protected virtual method; derived classes should then override that.
  • Jon Skeet
    Jon Skeet almost 12 years
    @supercat: Yes, that's another option - will add that.
  • Marshall
    Marshall almost 12 years
    @supercat thanks for your replay. But I'm not sure I have u understand right. Could u wirte me an short source code of your idea ? Just to make sure.. thanks
  • Marshall
    Marshall almost 12 years
    Thanks Jon. But I have just realized, that when I inherit abstract class, I cannot display my designer :/. So I did simple normal class, that inherit Form and also implemens interface. I put some controls that will be in every window. And that's it. Now I inheriet this class, so that common controls are always in the same place in every window. And I think (right now) that is the best solution (without abstract classes:/). Would u agree? edit. I mean, abstract classes are very useful, but I think in case of Forms, that's no sense to use them...
  • Jon Skeet
    Jon Skeet almost 12 years
    @Marshall: Again, I haven't done enough production UI programming to really have a view here. As Rok says, try to keep your UIs reasonably thin over something like a ViewModel, which makes this less of a problem.
  • supercat
    supercat almost 12 years
    @JonSkeet: Sorry if I seemed snippy. I should have said that in general, using expicit interface implementation without a virtual patch point is dubious because it prevents a derived class from chaining to a base implementation; it probably doesn't matter in this particular case because there isn't a useful base implementation. I'd still prefer to see the interface implemented to call a virtual patch point because unsealed derived classes which implement the interface should probably expose a virtual patch/chain point to child clases, and that may as well be done once in the base.
  • Jon Skeet
    Jon Skeet almost 12 years
    @supercat: No problem at all, and I agree. This sort of issue (and the need for a workaround) is one reason I try to avoid explicit interface implementation unless I really need it :)
  • Miro Hudak
    Miro Hudak about 9 years
    You can simply overcome this limitation with one surrogate non-abstract class, that is then used as super-class for the Form. I.e. AbstractMyForm -> MyFormSurrogate -> MyForm. This approach even allows to use generics in super-classes.
  • Rok
    Rok about 9 years
    @Miroslav Thanks! I updated my answer based on your comment. I am not sure if I was aware of that at the time of writing and afterwards I forgot about it. But I would still advise against this approach, since it usually degenerates into a mess.
  • Miro Hudak
    Miro Hudak about 9 years
    Sometimes, it is just necessary... E.g. I have implemented my own MVP infrastructure, and one of those is FormView (which is Form, that accepts Presenter instance) and that needs to be generic (so it provides, among other things) valid-typed Presenter property. If you always (by convention) include Surrogate class below the main class, it is not mess at all.
  • Rok
    Rok about 9 years
    I don't claim that should you need it, it shouldn't be done. But people less experienced with building UI might not even know about MVP and data binding and might end up building complex hierarchies full of codebehind in forms. I know I've done that and I would have preferred a pointer into a better direction sooner rather then later.