Interface Inheritance: What do you think of this:

When looking at our code base, I found an inheritance structure that looks like the following pattern:

interface IBase { void Method1(); void Method2(); } interface IInterface2 : IBase { void Method3(); } class Class1 : IInterface2 { ... } class Class2 : IInterface2 { ... } class Class3 : IInterface2 { ... } 

In Class2 , Method1 throws a NotImplementedException .

Questions:

  • What do you think about inheritance of interfaces in general?
  • Does the connection between IBase and Class2 IBase Liskov principle of replacement?
+4
source share
6 answers

Well, firstly, I'm generally against the implementation of the interface, throwing NotImplementedException exceptions. This is basically how to say: "Well, this class can also function as a calculator, mistakenly, almost."

But in some cases, this is really the only way to do something the “right way”, so I'm not 100% against it.

Just something to be aware of.

An interface is a contract that implements an interface that, as you say, abides by the contract. If you then begin to deny part of the contract, it sounds to me like a contract, or its implementation, was poorly thought out.


Edit : after choosing Greg Beech : if the interface specifically says that implementations should throw these exceptions, then this is part of the contract, then I agree that the class is fully allowed for this.


Regarding the principle of substitution, indicates that:

Let q (x) be a property provable with respect to objects x of type T. Then q (y) must be true for objects y of type S, where S is a subtype of T.

In this context, it violates the principle in the same way as overriding a method from a base class if you change what the method does in the descendant type.

The principle is described in more detail on the wikipedia page, as well as the following points (brackets and emphasis on my comments):

  • Preconditions cannot be strengthened in a subclass. (A precondition may be that "the class is ready to call this method at this point")
  • Postconditions cannot be relaxed in a subclass. (A postcondition may be that after calling the method, something is true about the state of the class)

Since you did not specify the full contract of your interfaces, only the declarative part that the compiler can verify is impossible to know that the principle is implemented for your implementation.

For example, if your Method2 has the following conditions associated with it:

  • May be called at any time.
  • Changes the state of an object that will be ready for the next event in the event chain

Then throwing a NotImplementedException violates the principles.

However, if the contract also states that:

  • For classes that do not support event chaining, this method should raise NotImplementedException or NotSupportedException

Then, probably, this is not so.

+10
source

So, I assume that you are asking the question:

If a derived type throws a NotImplementedException for a method where the base type does not, it does so violate the Lisk principle.

I would say that it depends on whether the documentation on the interface says that the method can throw this exception to fulfill its contract. If so, then this does not violate the principle, otherwise.

A classic example of this in the .NET framework is the Stream class, which has a bunch of operations, such as Read , Write and Seek , but there is no stream requirement to support all of these operations and is documented as throwing a NotSupportedException .

+4
source

Assuming that I understand what you mean, then I think the answer is yes, inheriting interfaces is good, and no, it does not violate the Liskov Substitution Principle.

The way to think about interfaces is the "behaves like" operator. It describes the set of behaviors to which the promises class obeys, expresses itself by methods, etc. Thus, there is no problem with the IBehavesLikeACat interface inheriting from the IEatsMice interface: if it behaves like a cat, then it obviously eats mice. Therefore, Cat will implement both, the ferret is only IEatsMice.

+1
source

First of all, inheritance in the interfaces is in order, it is used in the same way as for class inheritance, and is a very powerful tool.

Interfaces describe behavior, let's say an interface determines what a class can do, so if you implement an interface that you declare, you can do what that interface indicates. For instance:

 interface ISubmergible { void Submerge(); } 

So it’s obvious that if a class implements an interface, it can dive. Some interfaces, however, imply other interfaces, for example, imagine this interface

 interface IRunner { void Run(); } 

Defines an interface that indicates that the class that implements it can work ... however, in the context of our program it is understood that if something can work, obviously you can walk around, so you want to make sure that this is done:

 interface IWalker { void Walk(); } interface IRunner : IWalker { void Run(); } 

Finally, about the whole thing, NotImplementedException ... I am surprised at some suggestions. A NotImplementedException should never, ever be raised using a class interface method. If you implement an interface, you explicitly accept the contract that sets the interface, if you raise a NotImplementedException, you basically say "well, I lied, I told you that I support the interface, but I really do not."

Interfaces are designed to not worry about what the class implements and what doesn’t. If you take it away, they are useless. More importantly, your comrades will expect this behavior, even if you understand what you are doing, the rest of your team will not , and even you, after 6 months, do not understand the logic below This. Thus, class2 violates the common sense and purpose of the interface. Class2 does not implement IBase, so do not state what it does.

+1
source

Throwing NotSupportedException is OK: this is an exception if some interface features are not implemented by design.

This is less clear for a NotImplementedException: this is usually used for code that is not yet implemented, but will be. For example, stubs for implementing the interface created by Visual Studio 2008 contain the code "throw new NotImplementedException ()".

See the Brad Abram blog for a discussion of this.

+1
source

Interface inheritance is used in several places in the .Net framework. Therefore, although not everything that is there, I believe that it is visible as well. Take a look at the IEnumerable interface, for example.

As for throwing NotImplementedExceptions, I would say that it depends on how you use them in your code. You can, for example, define an interface with several methods, where some of them are optional. In this case, you should check if this method is available, and use it only if it was.

0
source

All Articles