4

One thing that always irked me (in C#) was that there's a hard dependency between an interface/abstract class and the implementing class and assembly. Meaning that that if two different assemblies implements the same interface either one of them have to reference the other (where the interface lies) or they both have to reference a third assembly with the interface.

It makes it harder to test different parts of an application separately and makes code much less flexible since you have to implement that specific interface. It also makes distributing libraries to third parties less tidy since if you want only to distribute part of your functionality you will either have to rework the class for thirdparties to include the interface, or have some silly assembly containing all but a interface in some cases.

Shouldn't there be a way to have ducktypeable interfaces? So for instance if you have two objects with a method that takes an interface as parameter, and each assembly has separate but identical interfaces, then you would be able to interchange the two.

I'm sure there are instances where we want the good 'ol strict interface dependencies we have right now but also having the possibility of "soft interfaces" might be a good idea? Or is the concept too convoluted and applicatable in too few situations (like multiple inheritance for instance). Are there languages which aren't completely ducktyped that have solved this issue and is there perhaps some designpattern to use to avoid the dependency?

Example:

Assembly A:

public interface ISomeInterface 
{
    ReadBooks();
    WriteLetters();
}

Public ClassA : SomeInterface
{
}

Assembly B:

public interface ISomeOtherInterface 
{
    ReadBooks();
    WriteLetters();
}

public class ClassB
{
    public DoStuff (ISomeOtherInterface someOtherInterface)
    {
      ....
    }
}

Here I'd like to have a Assembly C that references A and B and do:

  ClassA classA = new ClassA();
  ClassB classB = new ClassB()
  classB.DoStuff(classA as ISomeOtherInterface);

There's no direct dependency between A and B, but they can still be used together. I guess in this instance I could make an adapter class, but it feels clunky and in some instances not appropriate.

Specific casting is one way to go, another would be to declare an interface as dynamic (or whatever) and then it would only check that the interfaces are identical (but not that they are the same interface). A third way would to be able to specify "dynamic" on parameters so the object could allow or disallow that kind of interfaces.

Perhaps it even should be the other way around that unless you declare an interface as "explicit" you can always do that kind of typing.

4
  • I'm not sure I understand what you're saying - could you post a quick code example?
    – Michael K
    Feb 7, 2011 at 18:58
  • Added an example
    – Homde
    Feb 7, 2011 at 19:09
  • This seems a very specifically C# question, as in most object-oriented languages I'm familiar with some of your description would be meaningless. Feb 7, 2011 at 19:17
  • 3
    It's called structural typing and quite rare - which is a shame if you ask me.
    – user7043
    Feb 7, 2011 at 19:22

6 Answers 6

6

The intent of an interface is to completely separate the method signature from its implementation. If you are referencing an object strictly via an interface, but you need to call methods which are not specified as part of the interface, then maybe you should rethink your design.

1
  • Of course, but it also has a lot to do with assembly/package dependencies
    – Homde
    Feb 7, 2011 at 19:32
4

I am always amused when someone asks "why doesn't this feature exist" when it does in fact exist. :-)

It sounds like you want "no pia" type equivalence, which is a feature we added in C# 4. See this blog article for a brief introduction:

http://blogs.microsoft.co.il/blogs/sasha/archive/2008/10/29/pdc-day-1-no-pia-or-type-equivalence-and-type-embedding.aspx

Does that sound like the sort of thing you're looking for?

2
  • That seems to be more about com interop and assemblies than managed code and interfaces. I think what I was looking for is more like structural typing to make scenarios like the System.Addin (MAF) pipeline a bit more elegant.
    – Homde
    Feb 11, 2011 at 6:07
  • @MKO: It is about COM interop; that's what it's for. But the feature is basically structural equivalence on interfaces; I'm not saying that I'd recommend it's off-label use, but it certainly is possible to do so. Feb 11, 2011 at 6:40
3

If more than one class uses the same interface, that interface should be public and in it's own source file. Then the two class are completely interchangable. This concept is known as polymorphism. You can have many implementations, but one way to use them.

APIs use this concept. Java has the database API. It defines operations on databases, but has no implenting code. That is left up to the individual database vendors who know how to interface with that particular database.

The interface is usually distributed separately from the implementations. That allows the user to choose what implementation he wishes simply by passing the interface around rather than the implentation, i.e. a Connection rather than a AS400DatabaseConnection.

1
  • I don't think this addresses the question. The question is more "why can't we use duck-typing on interfaces", rather than "what is the point of interfaces" Feb 8, 2011 at 2:32
2

What you're asking for is structural typing. A type implements an interface if the type's signature (i.e. structure) matches the interface's. This is very useful when you have a logical dependency on a subset of an interface or class but don't want to depend on the whole of the interface/class.

Here's a similar stack overflow question - check out the first and second answers. The second links to a library for doing this, albeit with run-time type matching.

This would be a very useful extension, as it reduces coupling, leading to more understandable code and making mocking easier.

0
0

I may not understand you example correctly, but it seems like you could achieve some of this with the features that were added in .Net 4 like the Dynamic type. I am not certain you could do all of it, but some of the parameter controlled behavior is possible with use of DynamicMetaObject.

4
  • Dynamic resolves at run-time, this would still be resolved at compile time so there wouldn't be any performance penalty and you could still infer some structure
    – Homde
    Feb 7, 2011 at 22:16
  • It would if you wrote the interface around it, but I think you should be able to use a common dynamic object as your test data in your example, but for distribution you would have that issue unless you gave them a common ancestor. If you really wanted to avoid that you could always give type A and type B direct type operators to each other if you had to.
    – Bill
    Feb 7, 2011 at 22:33
  • @MKO Why would you infer a structure at compile time that is dynamic in nature? If you want to avoid the contract an interface provides and force it to be contingent on the type...not sure how you deal with such a thing at compile time versus runtime. Feb 8, 2011 at 20:26
  • It's not dynamic, just dependency free. A good example is the AddIn framework (MAF) if anyone have experience with it. The juggling of different interfaces and assemblies needed to have a plugin framework devoid of direct dependencies is a bit convoluted to say the least.
    – Homde
    Feb 8, 2011 at 20:59
0

I think what you want is the Dynamic keyword. For example, I recently had an instance where my domain objects all had 4 standard properties by convention but did not have a common ancestor. Knowing that they had these properties, I had a function that could take any of the domain objects as dynamic and manipulate those properties before passing it to the next in the chain. Hence I have ducktyping without needing a base class or interface.

You can do the same in your scenario.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.