Scott Hanselman says
every developer should be blogging. So I am going to try and blog and be
somewhat consistent.
One interview
question I have gotten in the past when interviewing for C# jobs is, "Can
an interface implement a method?" At first glance this is a simple
question that is meant to determine whether someone has a basic understanding
of what an interface is. The answer seems like a 'no', an interface is a
contract met by another object that provides the implementations for methods
defined by the interface. But here is a better answer, 'yes'. Using extension
methods you can attach behavior to an interface and then any class implementing
that interface will have access to those methods. Here is a quick example:
public interface
IPageableModel
{
int
TotalRows { get; }
int
PageSize { get; }
}
public static class
PageableModelExtensions
{
public
static int GetTotalPages(this IPageableModel pageable)
{
return
(int)Math.Ceiling((double) (pageable.TotalRows/pageable.PageSize));
}
}
So now anything that
implements IPageableModel will also be able to call GetTotalPages. Interfaces
have evolved from contracts to attachable behavior. You can now use
'Composition' to give objects behavior instead of 'Inheritance'. Given current
thinking that inheritance is a confusing pattern and that it is good to have
lots of narrowly defined interfaces attached to objects (Interface Segration
Principle of SOLID) , this is a great pattern to use. You can isolate a set of
logic into an interface even when that logic doesn't really stand on its own.
Here is another
potential usage pattern. One common usage of inheritance is to supply common services between a set of objects. In
web development it is very common to have all of your pages of controllers
descend from a common base that you have defined. That way you can essentially
share code between all the pages/controllers. But a common problem with this is
that your base page/controller is a mess and completely destroys any notion of
the S in SOLID (Single Responsibility Principle) because is a a collection of
unrelated 'services' to the actual objects. One response would be to divide
each set of responsibilities into one layer of inheritance and have all your
objects derive from massive chain of object inheritance. This would get pretty
confusing pretty fast and would limit flexibility. So a different way to do it
would be to just attach interfaces that
contain services to a page or controller. One result is containing all your
state in one object. Extension methods can not really hold any state and work
on state that the interface requires so any state will necessarily be defined
by the object. Personally I don't think this is a bad practice to have all the
state for an object defined in one spot while having different chunks of
behavior split into interface definitions. I wouldn't say you want to use this
pattern to replace all inheritance, but I think it is a good tool to organize
your code.
Of course, there is
the question of what happens if the actual class already implements the added
method, in the example above GetTotalPages. Well then this is used. Note that
you don't need override, virtual, or new keywords anywhere in this which is a little
dangerous. My code analysis tool, Resharper, also doesn't give me any warnings
about this form of overriding which is also bad. Also if you cast the object to
the interface you get the interfaces version of the method so both methods are
accessible. Another thing is that when you reference an interface extension
method inside the object implementing the interface the 'this.' is required
before the method. I actually like this particular behavior as it makes it
clear that the method isn't defined inside this object, but that it does belong
to the object you are in.
So all of this is a
little dangerous but fairly flexible, but the key is to not shoot yourself (or
the code maintaining your code) in the foot.
No comments:
Post a Comment