Reputation: 3142
I have a C# interface, and a concrete class that implements that interface. I now want to create another class that implements that interface. Simple enough.
However, most methods will be exactly the same in the classes, and only a couple of methods will actually change.
I don't want to duplicate all of the logic in my 2nd class that is contained in my first.
How do I create the 2nd class, and use the logic in my first class except for the extra stuff?
My interface is called IEventRepository, and my 1st class is called BaseEvents. I now want to create a new class called FooBarEvents.
My class definition for FooBarEvents is:
public class FooBarEvents : BaseEvents, IEventRepository
My intention was to then use the return base.Method() in each method that duplicates the code.
I'm assuming this isn't correct?
Upvotes: 11
Views: 42356
Reputation: 6112
FooBarEvents
should only need to inherit from BaseEvents
, not also implement IEventRepository
, as BaseEvents
already implements the interface. If you need to change the behavior of some IEventRepository
methods in FooBarEvents
, just override those methods.
Edit: some examples
interface IEventRepository
{
void CommonMethodA();
void CommonMethodB();
void ImplentationSpecificMethod();
}
abstract class BaseEvents : IEventRepository
{
public void CommonMethodA()
{ ... }
public virtual void CommonMethodB()
{ ... }
public abstract void ImplementationSpecificMethod();
public void BaseEventsMethod()
{ ... }
public void BaseEventsMethod2()
{ ... }
}
class FooBarEvents : BaseEvents
{
public override void CommonMethodB()
{
// now FooBarEvents has a different implementation of this method than BaseEvents
}
public override void ImplementationSpecificMethod()
{
// this must be implemented
}
public new void BaseEventsMethod2()
{
// this hides the implementation that BaseEvents uses
}
public void FooBarEventsMethod()
{
// no overriding necessary
}
}
// all valid calls, assuming myFooBarEvents is instantiated correctly
myFooBarEvents.CommonMethodA()
myFooBarEvents.CommonMethodB()
myFooBarEvents.BaseEventsMethod();
myFooBarEvents.BaseEventsMethod2();
myFooBarEvents.FooBarEventsMethod();
myFooBarEvents.ImplementationSpecificMethod();
// use the contract thusly:
void DoSomethingWithAnEventRepository(BaseEvents events)
{ ... }
Upvotes: 19
Reputation: 113382
There's a few different approaches.
One. Skip the interface entirely, and make it an abstract class. This is simpler when it works, but the fact that you can only have one base class restricts use in C#
public abstract class EventRepository
{
public abstract int MustBeOverridden(string str);//classes have to override this
public virtual int CanBeOverridden(int i)//classes can override but may choose not to.
{
return 4;
}
public int CannotOverride(string str)//this is always the same
{
return MustBeOverridden(str) + 3;//can make use of this
}
}
You can have one class implement the interface, and another derive from it:
public interface IEventRepository
{
int Method1(string str);
int Method2(string str);
}
public class EventClass1 : IEventRepository
{
public int Method1(string str)//can't be overridden as not marked virtual
{
return 1;
}
public virtual int Method2(string str)//can be overridden
{
return 2;
}
}
public class EventClass2 : EventClass1
{
public override int Method2(string str)
{
return -2;
}
}
Have them both override an abstract class that gives some common behaviour:
public abstract class EventClass : IEventRepository
{
public abstract int Method1(string str);
public int Method2(string str)
{
return 2;
}
}
public class EventClass1 : EventClass
{
public override int Method1(string str)
{
return 1;
}
}
public class EventClass2 : EventClass
{
public override int Method1(string str)
{
return -1;
}
}
They might also use a static helper class that has nothing to do with the hierarchy, but which does provide methods that are useful in implementing the functionality.
Be wary though of this pattern:
public class EventClass1 : IEventRepository
{
public int Method1(string str)//not override-able
{
return 1;
}
public int Method2(string str)//not override-able
{
return 2;
}
}
public class EventClass2 : EventClass1, IEventRepository
{
//We really want our own Method1!
public new int Method1(string str)
{
return 3;
}
int IEventRepository.Method1(string str)
{
return -1;
}
}
EventClass2 e2 = new EventClass2();
EventClass1 e1 = e2;
IEventRepository ie = e2;
Console.WriteLine(e2.Method1(null));//3
Console.WriteLine(e1.Method1(null));//1
Console.WriteLine(ie.Method1(null));//-1
Even when IEventRepository.Method1
is defined more sensibly, the above is likely to lead to confusion.
Upvotes: 1
Reputation: 32780
Use inheritance:
public interface IFoo
{
void GeneralBehaviorMethod1();
void GeneralBehaviorMethod2();
void SpecificBehaviorMethod1();
}
public class Bar: IFoo
{
public void GeneralBehaviorMethod1() {...}
public void GeneralBehaviorMethod2() {...}
public virtual void SpecificBehaviorMethod1() {...}
...
}
public class BarOnSteroids: Bar
{
public override void SpecificBehaviorMethod1() {...}
}
BarOnSteroids
will inherit all behavior of Bar
and you can alter the specific behavior of any methods you need by overriding them in BarOnSteroids
(they need to be marked as virtual in the base class Bar
).
This way you would have the following:
IFoo iFoo = new Bar();
iFoo.SpecificBehaviorMethod1(); //Bar implementation will be called;
IFoo iFoo = new BarOnSteroids();
iFoo.SpecificBehaviorMethod1(); //BarOnSteroids implementation will be called.
iFoo.CommonBehaviorMethod1(); //Bar implementation will be called.
Bar bar = new BarOnSteroids();
bar.SpecificBehaviorMethod1(); //BarOnSteroids implementation will be called.
bar.CommonBehaviorMethod1(); //Bar implementation will be called.
This assumes you want to change specific behavior of methods that are part of the IFoo
interface. If all you want is to add additional functionality to BarOnSteroids
then simply inherit form Bar
to inherit all it's functionality and add all required new methods to implement the new functionality.
Upvotes: 2
Reputation: 15931
The following code shows how to provide a common implementation of some interface methods with an abstract base class, and provide custom implementations for others.
public interface IEventRepository
{
void Method1();
void Method2();
}
public abstract class BaseEvents : IEventRepository
{
public void Method1()
{
Console.WriteLine("This is shared functionality");
}
public abstract void Method2();
}
public class Implementation1 : BaseEvents
{
override public void Method2()
{
Console.WriteLine("Impl1.Method2");
}
}
public class Implementation2 : BaseEvents
{
override public void Method2()
{
Console.WriteLine("Impl2.Method2");
}
}
public class Program
{
static void Main(string[] args)
{
var implementations = new List<IEventRepository> { new Implementation1(), new Implementation2() };
foreach (var i in implementations)
{
Console.WriteLine(i.GetType().Name);
Console.Write("\t");
i.Method1(); // writes 'This is shared functionality'
Console.Write("\t");
i.Method2(); // writes type specific message
}
}
}
Upvotes: 5
Reputation: 51369
Since BaseEvents
already implements IEventRepository
, you don't need to implement it again in FooBarEvents
. FooBarEvents
automatically inherits BaseEvents
' implementation.
Upvotes: 6
Reputation: 46760
You can make your second class extend your first class. Your first class can be abstract but only implement the common methods from the interface.
Upvotes: 2
Reputation: 53313
Why don't you define your methods in the base class as Virtual
and override the ones that you want to change in the child class?
Upvotes: 3
Reputation: 8623
If a certain selection of methods in the BaseEvents
implementation of IEventRepository
are always going to maintain the same implementation, then you can just implement them in the BaseEvents
class and mark the ones that might change as virtual
. That way, if FooBarEvents
wishes to change the implementation of one of the methods, it can simply override it.
Just a note with regards to adding IEventsRepository
to your FooBarEvents
class: it is valid to do that. See here for a Jon Skeet answer about it.
Upvotes: 0