I recently worked with an architect who structured his base class like this:
public abstract class Base<T>
{
public abstract T Get(int id);
internal T InternalGet(int id, IRepository<T> repository)
{
// Do more magic
return repository.Get(id);
}
}
And then in the derived class, if you just want to use the base functionality, you'd have to..
public class Derived : Base<T>
{
private readonly IProductRepository _repository; // Implements IRepository<Product>
// Ctor with dependency injection, this is good stuff!
public DerivedClass(IProductRepository repository)
{
_repository = repository;
}
public override Product Get(int id)
{
// ... explicitly call base functionality - NOT a call to base though!
return InternalGet(id, _repository);
}
}
Why not just pass the repository to the base class, and override when you need to?
public abstract class Base<T>
{
private readonly IRepository<T> _repository;
protected Base<T>(IRepository<T> repository)
{
_repository = repository;
}
public virtual T Get(int id)
{
// Do magic
return _repository.Get(id);
}
}
And then in the derived class, if you don't want to use the base method, just override it.
public class Derived: Base<Product>
{
private readonly IProductRepository _repo;
public Derived(IProductRepository repo) : base(repo)
{
_repo = repo;
}
public override Get(int id)
{
if(! customerIsBeingNice)
throw new GoAwayException();
return _repo.Get(id);
}
}
I think the architect was trying to avoid the call super code smell, but since we are not requiring a call to super - in fact it really should never happen, because if you override the method, you are supposed to implement the flow you want, whereas if you call super, you can't hook into the flow that easily.
Which of these is better/worse, and why? Any alternatives?