简体   繁体   中英

C#: Interface and Abstract to enable Implement and Override

I've got to design about 5 different classes.

A lot of the parts of these classes will be very similar, but they will have slight differences (of course).

If I write an interface that each of my designed classes implement, then each abstract method in the interface has to be completely written.

If I write a base class that each of my designed classes derives from, then each class will automatically have some functionality in the virtual method that I create in the base class, but they would all need to be overridden, calling the base functionality, to include the slight differences.

Is there a way to combine these features? I like requiring the interface 's methods to be implemented, but I also like having set features pre-programmed by a base class.

I've looked at many examples here and elsewhere, but it does not look like anyone does what I am describing. Is it even possible?

EDIT: So, given this:

abstract class Base
{
    virtual protected void OptionallyOverridable() {}
    abstract protected void SubclassMustImplement();
}

...is there a way to write something that does like this:

abstract class Base2
{
    DataEventType EventType;
    DataChangedEventHandler OnDataChange;

    virtual protected void OptionallyOverridable() {}
    abstract protected void SubclassMustImplement() {
      // values here are guaranteed
    }
}

C# allows a class to both inherit from a base class and implement an interface, so why not just do both?

public interface IFoo
{
    public void Bar();
    public bool Baz();
}

public abstract class BaseFoo : IFoo
{
    //fields/properties used in all classes
    public void Bar()
    { //Implementation }

    public bool Baz()
    { //Implementation }
}

public class DerivedFoo : BaseFoo, IFoo {...}

AllenG got my plus one, but since I had already typed this out, here is a lengthier and more explicit demonstration of the concept...

Define your interface...

public interface IFoo
{
    void DoIt();
    void DoItWithoutDefaultBehavior();
}

Define a base class that implements the interface with some default behaviors, or perhaps some methods don't have a default behavior...

public abstract class BaseFoo : IFoo
{
    public virtual void DoIt()
    {
         // Base behavior
         Console.WriteLine("base");
    }

    // This one has no base behavior
    public abstract void DoItWithoutDefaultBehavior();
}

Some of your subclasses might use those default behaviors ...

public class DerivedFoo1 : BaseFoo, IFoo
{
    // Doesn't override DoIt, takes BaseFoo

    public override void DoItWithoutDefaultBehavior()
    {
        Console.WriteLine("foo1");
    }
}

Others might add to them ...

public class DerivedFoo2 : BaseFoo, IFoo
{
    public override void DoIt()
    {
        base.DoIt();
        // Additional stuff
        Console.WriteLine("derived");
    }

    public override void DoItWithoutDefaultBehavior()
    {
        Console.WriteLine("foo2");
    }
}

You can call the methods through the class or the interface.

void Main()
{
    var foo1 = new DerivedFoo1();
    foo1.DoIt();

    var foo2 = new DerivedFoo2();
    foo2.DoIt();

    IFoo foo1AsFoo = new DerivedFoo1();
    foo1AsFoo.DoIt();

    IFoo foo2AsFoo = new DerivedFoo2();
    foo2AsFoo.DoIt();
}

See also: Eric Lippert's post which discusses whether DerivedFoo1 and DerivedFoo2 should restate that they implement IFoo when BaseFoo already says so. They do in my example for the sake of being explicit.

EDIT It's definitely possible to add events to the interface. I made the following changes to my example. You could make similar changes:

  • To interface IFoo , add event EventHandler TheEvent;
  • To BaseFoo , add public event EventHandler TheEvent;
  • To BaseFoo.DoIt , add if (TheEvent != null) { var args = new EventArgs(); TheEvent(this, args); } if (TheEvent != null) { var args = new EventArgs(); TheEvent(this, args); }
  • Add public void TheHandler(object sender, EventArgs e) { Console.WriteLine("Fired."); } public void TheHandler(object sender, EventArgs e) { Console.WriteLine("Fired."); }
  • To Main , add foo1.TheEvent += TheHandler;

The output now becomes

base
Fired.
base
derived
base
base
derived

Yes and you already answered yourself. You will do both:

  • Have a base class with basic implementation
  • Have child classes (or base class, why not?) implement the interfaces you want.

You can mix both interface and abstract, I think what you want is something like this

public interface IFoo
{
    void ImplementMe();
    int ImplementId { get; }
}

public abstract class BaseFoo : IFoo
{
    public virtual void ImplementMe()
    {
        CommonStuff();
    }

    public abstract int ImplementId { get; }

    private void CommonStuff()
    {
        // ... do stuff ?
    }
}

public sealed class FooImplementationA : BaseFoo
{
    public override int ImplementId { get { return 0; } }

    public override void ImplementMe()
    {
        MoreStuff();
        base.CommonStuff();
    }

    private void MoreStuff()
    {
        // ... do more stuff.
    }
}

public sealed class FooImplementationB : BaseFoo
{
    public override int ImplementId { get { return 1; } }

    public override void ImplementMe()
    {
        DifferentStuff();
        base.CommonStuff();
    }

    private void DifferentStuff()
    {
        // ... do different stuff.
    }
}

but then again you don't really need the interface and can simply get away with using the BaseFoo abstract class

The 'abstract' keyword is what you are looking for.

    abstract class Base
    {
        virtual protected void SubclassCanCallAndOptionallyOverride() {}
        abstract protected void SubclassMustBeImplement();
    }

For more details: http://msdn.microsoft.com/en-us/library/ms173150.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM