Reputation: 3702
So I am still very new to C# and using interfaces, and when I thought I understood them I realized I don't completely. The confusion I have found that I am seeking some clarification here for is, when you create an interface, and have a class inherit from it
public Interface ISomeInterface
{
//some methods/properties
}
public class FooClass : ISomeInterface
{
//implemented ISomeInterfaces methods/properties
}
And you use this class object in an implementation somewhere in your program
public class BarClass
{
private ISomeInterface _someInterface;
public BarClass(ISomeInterface someInterface)
{
_someInterface = someInterface;
}
//rest of class
}
My confusion is why do I see it setup this way. I thought that I would have instantiated a new object of type FooClass, as well as used an object of type FooClass in the constructor as such:
public class BarClass
{
private FooClass _fooClass;
public BarClass(FooClass fooClass)
{
_fooClass = fooClass;
}
//rest of class
}
What am I missing to understanding this? I didn't think I would directly be declaring objects of an Interface?
Thanks in advance.
Upvotes: 1
Views: 125
Reputation: 384
Another way of thinking about the interplay between interfaces and classes is to flip them upside down. That means to start with classes first. Let's say you have several classes that expose a method called "Sort()". Then you have another class that has a method that requires references to these classes and in turn calls their "Sort()" methods. Instead of having several methods with different parameters, you can create and attach an interface to those classes (very quick fix as these classes already contain the implementation).
A.Sort()
B.Sort()
C.Sort()
interface ISortable {void Sort();}
A : ISortable
B : ISortable
C : ISortable
D.SortSomething(ISortable foo)
{
foo.Sort()
}
Maybe this is too abstract. My favorite use of interfaces is enabling my classes to participate in foreach loops.
class SomeCollection : IEnumerable
{
List<SomeItem> _items = new List<SomeItem>();
// This is the only code I need to enable this class to participate in foreach loop.
public Enumerator GetEnumerator()
{
return _items.GetEnumerator();
}
}
Once you discover how interfaces can simplify your codes, you can even begin creating interfaces before writing your classes.
Upvotes: 0
Reputation: 1039358
The idea is that BarClass
should not be tightly coupled to a specific implementation of ISomeInterface
.
If you use this:
public BarClass(FooClass fooClass)
it means that the BarClass can work only with this specific FooClass implementation and nothing else. Whereas if you use:
public BarClass(ISomeInterface fooClass)
now the BarClass
is no longer tightly coupled to FooClass
. This means that the consumer of the BarClass
can now pass any implementation of the interface he wants as long as it respects the defined contract (interface). So if he wants FooClass
he passes an instance of FooClass
, but if he is not satisfied with FooClass
he can write his own implementation and pass it to the constructor and from the point of view of the BarClass
this is absolutely transparent (it doesn't need to be modified).
The weak coupling between your classes is one of the most fundamental aspects of OOP as it allows you to easily replace one component with another without having to rewrite your entire application.
Upvotes: 7
Reputation: 27421
One of the main benefit to program to ISomeInterface instead of FooClass, is that you might probably change your implementation of FooClass. For example, consider a database driven blog application:
interface IBlogStorage{
getPosts();
}
you then have a class like:
class XMLBlogSotrage: IBlogStorage{}
and suppose you implement everything to the interface. later on, you think XML is too slow and you want to use RDBMS, then:
class MsSQLBlogStorage:IBlogStorage{}
In this case, you don't need to change anything in other codes, you just need to create a new class and plug it in! Those already existed codes, doesn't need to bother where is the storage.
Upvotes: 0
Reputation: 24927
By using the interface definition instead of the concrete implementation, your code is now more loosely coupled. This technique is used in dependency injection.
In addition, this comes in handy when you need to need to implement FooClass
differently. If you used the concrete implementation, you will need to make code changes where ever you have declared FooClass
. Programming against the interface shields you from the effects of such changes.
Upvotes: 0
Reputation: 11833
Do you have a C/C++ background? Then you should be aware that
private ISomeInterface _someInterface;
would be written as
private:
ISomeInterface& _someInterface;
In C++ (assuming you have an abstract base class called ISomeInterface).
This means you are storing a reference to an object implementing ISomeInterface not such an object itself. The advantage of this is that you can pass ANY object to BarClass that implements ISomeInterface which gives you more flexibility, e.g. for unit testing.
Upvotes: 0
Reputation: 27515
Suppose FooClass wrote something to a database. You'd like to test BarClass without having to actually set up a database. If you created a different TestFoo that implemented the same interface, you could pretend to be the database and more easily test your class; BarClass wouldn't have to know that it wasn't talking to the 'real' FooClass.
Upvotes: 1