Real World Interfaces in C#

by percent20 11/26/2007 10:20:00 AM

I have been on a bit of a "quest" lately to learn interfaces better. While at work I hit up a couple of fellow developers on "why" you should use interfaces in the real world. Believe it or not after going through some code and getting some commentary on it I think I have an understanding of interfaces.  Here is my understanding in a possible "real world" situation.

Let’s say you want to render out commonly used objects to the screen.  They can be textbox's, images, or even labels.  Each of these might have a common set of properties like title, id, width,  and height; plus a method like Render() to show it on the screen.  Now in .NET we might call these objects controls so we will use that naming convention for example sake.  You might create an interface called IControl that all controls will inherit from.  One reason to use an interface instead of a separate class is because the render method could be different for all the different controls, but is all that is needed to be called in order to show the control.

So, let’s look at some basic code.  First we will look at the interface.

IControl Interface

This interface IControl has our common properties and the render method. We are going to implement different render methods for each of our different controls so we might not necessarily want to create a control class to inherit from. To illustrate this more let’s look at two different controls implementing the IControl interface

TextBox

TextBox Class Implementing IControl

Label

Label Class Implementing IControl

If you notice both the TextBox and the Label controls have slightly different render methods, but both contain the same properties because of the IControl interface. This is important to note because we KNOW that if the IControl interface is being used that you can always call the methods and properties from them. So that means you can make a method like the following which will always call the render method as long as the object implements the IControl interface no matter what the control is.

OutPut Method that calls IControl Render Method

With this you can create an instance of TextBox and Label and pass both of them to the above method and they will call the render method and output the correct information.

Here is some “example” code on how-to use and put together everything above.

Main Method Implementing Controls

Conclusion

To wrap it up you can make an interface and an interface basically says “hey I have at the very least these properties and methods and you can use them however you need without worrying about what they do to actually use them” Which means that you can write any code you want to implement each of the properties and methods and as long as you use the interface as your “datatype” there is no need to worry about what the code actually does for each and every object that implements the interface. In the case of the example there is no need to worry about how many or what the controls actually do when rendered because they will all be rendered by using the output method since the datatype of the parameter is IControl.

Please, feel free to leave comments and critiques on this. I am still learning about interfaces and this is as “real world” as I could figure out on how to use interfaces as that is what helps learn. Any help would be great and please feel free to download the code I have attached and play with it a bit. I am sorry for the length I just wanted to be thorough, I hope I was.

 

Interfaces.zip (6.33 kb)

kick it on DotNetKicks.com

Currently rated 4.0 by 4 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

.NET | Tutorials | Programming

Related posts

Comments

11/26/2007 11:40:52 AM

Jake Good

Be careful with interfaces... they aren't a golden hammer.

For example, you could use abstract classes and virtual methods to achieve what you wanted to in your example, with having shared functionality in your base class. This also leads to class mashing once the interfaces do change.

The point being that when you start working with interfaces, think of them as contracts. If the contract changes something gets broken...

One common technique is to implement an interface, then create a class (abstract or not) that will implement the interface AND some base implementation.

In your example, IControl is fine... now define a BaseControl abstract class that defines title, height, width, and ID implentations (since they seem to be exact between subclasses)... That way your TextBox class only has to worry about it's render method and can still live to the contract and base class. Put another method on your Interface? You are in luck if it has common implementation in the Base Control.. write it there and no more broken code!

Jake Good us

11/26/2007 12:14:54 PM

percent20

I was talking to a guy int he office a bit about that though I like your idea of the abstract class for the base class. After talking to him and from what you have said I think I am going to extend this post into a series of posts over interface to cover more detail on them.

This is a fun/interesting subject to learn about and can't wait to do more research and more posts to learn more.

percent20 us

11/26/2007 6:56:15 PM

Chad Myers

Interfaces are a way of separating the implementation from the usage. As an API writer, I want to know that there is going to be an ISomethingFactory that will create instances of ISomething's for me. All I care about is the ISomethingFactory.CreateSomething() method and the ISomething.DoSomething() method. I can then write very de-coupled code that allows me to not worry about implementation details. A good, concrete example of this is database abstraction for a data-access component/library/layer/whatever. Check out the IDbConnection, IDbCommand, etc in the .NET Framework System.Data and children namespaces.

One immediate, tangible benefit of this decoupling is that you can more easily write tests on your layers by being able to completely lift out a layer without necessarily dragging the whole rest of the application with it (as though they were sticky-glued together).

If I have a PurchaseOrderService which performs service-type work with PurchaseOrders (for example, submitting a purchase order to the financial accounting system and also saving a copy of the PurchaseOrder entity to the database), I might have the PurchaseOrderService depend upon the FinancialAccountingSystemService and the PurchaseOrderRepository.

Well, when I'm testing PurchaseOrderService, I don't want to have to worry about the side-effects and dependencies of testing the FinancialAccountingSystemService (henceforth FASService) and the PurchaseOrderRepository (PORepo). So I make the the FASService and PORepo implement the IFASService and IPORepo interfaces and pass (dependency-inject) those interfaces into the C'tor of PurchaseOrderService, like so:

public class PurchaseOrderService
{
....private IFASService _fasService;
....private IPORepo _poRepo;

....public PurchaseOrderService(IFASService fasService, IPORepo poRepo)
....{
........_fasService = fasService;
........_poRepo = poRepo;
....}
}

Then, in my unit tests, I can simple mock (using Rhino.Mocks) bogus, dummy/mock implementations of IFASService and IPORepo so that I can explicitly control their behavior during tests. This allows me to focus PURELY on testing PurchaseOrderService and *NOT* all three (POService, FASService, and PORepo).

Chad Myers us

11/26/2007 7:17:30 PM

trackback

Trackback from DotNetKicks.com

Real World Interfaces in C#

DotNetKicks.com

11/27/2007 11:10:51 AM

Joseph Holsten

Don't forget how important common interfaces can be. For example, while most of us just use a List<>, you can write your own class to implement IEnumerable, and then iterate over it with a for.
Similarly, implement the IComparable interface to compare to another object. No value object is complete without it!

Well known and well understood interfaces let people use your code quicker, because they can assume what will happen.

Joseph Holsten us

11/27/2007 11:31:43 AM

percent20

Thanks for the tip. I will for sure take a look at those to get a better understanding of interfaces.

percent20 us

11/27/2007 3:16:58 PM

Geovanny Tejeda

Hopefully this can contribute to the post, here's how I personally choose between abstract classes and interfaces in my projects.

I only use Interfaces to separate "special" functionality, by special i mean something that is specific only to some classes (if i have common functionality for a set of classes and all of them will share that commonality i use abstract classes).

So, with that in mind:

public abstract class Page
- public abstract void ToString

public interface IPrintable
- RenderForPrinting

Now you can have a derived class like
public class ReportPage: Page, IPrintable

In this example all the pages will have a common functionality but only few specific pages like the report pages will have printing capabilities.

Hope if helps.
Thanks

Geovanny Tejeda do

11/27/2007 10:36:56 PM

Armen Ayvazyan

Described technique in OOP calls Polymorphism. I personally think Polymorphism is the most powerful feature in OOP. Almost all design patterns built on it.

Armen Ayvazyan cz

12/2/2007 11:01:23 AM

pingback

Pingback from rtipton.wordpress.com

Weekly Link Post 18 « Rhonda Tipton’s WebLog

rtipton.wordpress.com

12/14/2007 10:57:09 AM

Havagan

Late to the game, but hey, I'm a new subscriber.

Another key concept with Interfaces, is that it's a form of multiple inheritance. .NET only allows you to inherit from one base class, but you can implement multiple interfaces.

You can do much of what an abstract class does via class inheritance (i.e. have different behavior for your Render() methods). But abstract classes are limiting. If you want the same functionality to span two classes that don't inherit from a common parent you need to:

a) re-code the Render() functionality in two classes
b) re-code the classes to have some shared abstract parent class where the Render() method signature is defined.

Neither one is very maintainable. Option a) means trying to synchronize method signatures (assuming you want to call Render() in the same way every time) while option b) means recoding a bunch of classes.

To steal your example, if you used class inheritance to define an abstract Render() method in a WebControl parent class that Label and TextBox would inherit from, you could get the same behavior as your example without using Interfaces. i.e. WebControl.Render(), Textbox.Render() and Label.Render() are all valid.

But, if you had another class named XmlDocument that did not inherit from WebControl, how would you have it implement Render() without resorting to options a) or b) above? I mean, we do want to occasionally render an XML document, right?

If you did create multiple Render() methods how would you test for Render() support among a collection of different objects? A bunch of "is" checks?

if (instance is XmlDocument || instance is WebControl) { ... }

What if one of the Render() method signatures change?

That's where Interfaces come in. An Interface would define Render() and both the XmlDocument and WebControl classes could implement the Render Interface in their own way. The common thread is the Interface. Our collection of different objects checks is simplified:

if (instance is IRenderable) { ... }

and if the Render() method signature changes in the Interface, the compiler lets you know.

Paul

Havagan us

1/22/2008 1:06:34 PM

pingback

Pingback from weblogs.asp.net

I have arrived - Beginnermediate ASP.NET

weblogs.asp.net

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

8/7/2008 1:30:30 PM

Powered by BlogEngine.NET 1.3.0.0
Theme by Mads Kristensen


My Flare

AddThis Feed Button

National Blog Posting Month

Eagle Scout

I'm Test Driven

[Reserved for MVP status I want to earn]

View Buddy Lindsey's profile on LinkedIn

Twitter



Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Sign in