.net does not allow partial interface implementation in base classes. As a mitigation I've come to 3 alternate solutions. Please help me decide which is more universal in terms of refactoring, compile/run time errors, readability. But first a couple of comments.
- Of course you may always cast object to IFoo and call any method without any compiler warning. But it's not logical, you wouldn't do that normally. This construct wouldn't occur as a result of refactoring.
- I want maximum separation. Direct class contract (public methods and properties) should be separated with interface implementations. I use interfaces a lot to separate object interations.
My comparison:
- BaseClass1/MyClass1:
- con: Have to create virtual abstract in BaseClass1 for each not implemented method of IFoo.
- con: Additional method wrap - slight productivity impact at runtime.
- BaseClass2/MyClass2:
- con: no compiler warning if no implementation of Method2 in MyClass2. Runtime exception instead. Refactoring with poor unit test coverage may potentially destabilize code.
- con: has to put additional obsolete construct to prevent direct method call from child classes.
- con: Method2 is public for BaseClass1 so it's part of class contract now. Have to put "Obsolete" construct to prevent direct call, not via IFoo.
- BaseClass3/MyClass3:
- pro: (Compared to #2). More readable. You see that MyClass2.Method2 is IFoo implementation, not just some overriden method.
public interface IFoo
{
void Method1();
void Method2();
}
public abstract class BaseClass1 : IFoo
{
void IFoo.Method1()
{
//some implementation
}
void IFoo.Method2()
{
IFooMethod2();
}
protected abstract void IFooMethod2();
}
public class MyClass1 : BaseClass1
{
[Obsolete("Prohibited direct call from child classes. only inteface implementation")]
protected override void IFooMethod2()
{
//some implementation
}
}
public abstract class BaseClass2 : IFoo
{
void IFoo.Method1()
{
//some implementation
}
[Obsolete("Prohibited direct call from child classes. only inteface implementation")]
public virtual void Method2()
{
throw new NotSupportedException();
}
}
public abstract class MyClass2 : BaseClass2
{
public override void Method2()
{
//some implementation
}
}
public abstract class BaseClass3 : IFoo
{
void IFoo.Method1()
{
//some implementation
}
void IFoo.Method2()
{
throw new NotSupportedException();
}
}
public abstract class MyClass3 : BaseClass3, IFoo
{
void IFoo.Method2()
{
//some implementation
}
}