Do Not Repeat Yourself or Encapsulation?
Let's say I created the following:
I'd like to make Marker implement the IMask interface. But then I'd be REPEATING MYSELF (check the code in the end) Or I could my the Spot within the Marker public. But then I'd be exposing the implementation of my class. Or I could my Spot inherit from Spot, but this is not the ideal solution, since semantically a Marker is not a specific type of Spot.
And what if I create another class that has a Spot as a field AND I want, again, to implement the IMask interface? I would be repeating myself AGAIN. So, how should I proceed? Should I make the List within Spot public? And then make the Spot in Marker public? Or should I repeat the calls?
interface IMask : IList<Point>
{
public void MoveTo(Point newCenter);
// ... other Methods
}
public class Spot : IMask
{
List<Point> points;
public void DoSpotyStuff()
{
// blabla
}
// Other methods
// ...
// Finally the implementation of IMask
public void MoveTo(Point newCenter)
{
// blabla
}
// And of course the IList methods
public void Add(Point newPoint)
{
points.Add(newPoint);
}
}
public class Marker : IMask
{
private Spot mySpot;
private int blargh;
// Other fields
public void MarkeryMethod()
{
// Blabla
}
// HERE IS THE PROBLEM: Should I do this and repeat myself
public void MoveTo(Point newCenter) { mySpot.MoveTo(newCenter); }
// And here I'm REALLY starting to repeat myself
public void Add(Point newPoint) { mySpot.Add(newPoint); }
}
Observations: The interface IMask is not inheriting from List. It's implementing the IList interface, which in turn implements ICollection, IEnumerable Assume that Marker is NOT, semantically, special kind of Spot. So, even though I could Inherit from Spot and solve the issue, it would not be the best solution.
An interface is to establish a kind of contract that the class that will implment it will have this methods. So what you can do is an absctract/base class that implements your Interface and then the classes Marker and Spot can inherit from the base class and you are all set and good to go.
public abstract class BaseClass : IMask {...}
public class Marker : BaseClass{...}
public class Spot : BaseClass{...}
UPDATE January 2020 : Within C#8 you can have default interface methods with implementation (which basically kills the use case for abstract classes), you can take a look here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods
Seems to me your choice should be based on how you expect the application to grow, i.e. forward compatibility.
If you think Marker is going to evolve, e.g. maybe some day it will contain more than one Spot, or more than one object that supports IMask, then repeating yourself is the way to go, because you're going to want to coordinate the calls to MoveTo and Add for all of the objects contained in the Marker, and you'll be glad there is a layer of indirection in Marker.
If you think Spot is going to evolve, e.g. if Spot is going to have more methods added like ChangeSize or Remove, perhaps the best thing to do is expose the Spot as a public property of Marker with type IMask. That way the new properties are immediately exposed without writing additional wrapper code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With