This blog has moved!

Check out www.CodeBetter.com/blogs/grant.killian

<July 2008>
SuMoTuWeThFrSa
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789


Navigation

Professional Props...

Extracurricular Props...

Subscriptions

Article Categories



Wednesday, August 27, 2003 - Posts

Implementation Inheritance, or Interface Inheritance, that is the Question

We recently covered VB.Net OO topics in our class and the question came up regarding when to Inherit from a base object (Implementation Inheritance) versus when to Implement an interface (Interface Inheritance).  While the two approaches are not mutually exclusive, and can be very powerful when used together, let me share my thoughts on the matter.

The Inherits keyword brings all the implementation details of the parent class into the derived class; this is an elegant means of code reuse and allows for polymorphism via inheritance.   Take the following object model showing Inheritance:

Public Class BaseBizObject

    Private _strState as String

    Public Property State As String

        Get

            return _strState

        End Get

        Set( val as String )

            _strState = val

        End Set

    End Property

    Public Sub LogState()

        'save state somewhere...

    End Sub

End Class

Public Class PersonBizObject

    Inherits BaseBizObject

    'Specific Implementation of PersonBizObject Methods

End Class

Public Class OrderBizObject

    Inherits BaseBizObject

    'Specific Implementation of OrderBizObject Methods

End Class

 

All our specific business objects (PersonBizObject, OrderBizObject, and any others we create in our business object layer) implement the LogState behaviour courtesy of the BaseBizObject object.  We only have to write the code to LogState()  in our parent object, and the implementation cascades down to all the derived objects.  If we ever needed to implement new functionality common to all our business objects, all we have to do is include the code in the BaseBizObject and voila, we’re good to go.  This is how Implementation Inheritance works; it’s great when creating a closely coupled pattern of reuse in an object model.  I’ve worked on many projects where we create a base object for whatever application tier we’re working on, just to provide an easy way to implement common functionality (such as LogState()).

 

The Implements keyword binds a class to a specific contract, but has no impact on implementation; this is an elegant means of code reuse but in a completely different way than the Inherits keyword.   This is also known as “Interface Inheritance.”  Take the following code:

Public Interface ILoggable

    Sub LogState()

End Interface

Public Class PersonObject

    Implements ILoggable

    Public Sub LogState() Implements ILoggable.LogState

        'log Person state to the Person table, text file, whatever

    End Sub

End Class

Public Class OrderObject

    Implements ILoggable

    Public Sub LogState() Implements ILoggable.LogState

        'log Order state to the Order table, text file, whatever

    End Sub

End Class

 

The ILoggable Interface enforces a LogState() method on every type that implements it.  We don’t have LogState behaviour (i.e. code) we want to share between our PersonObject and OrderObject, but we are interested in binding the objects to the ILoggable contract so that we could write the following code:

    Sub EventHandler()

        Dim objPerson as New PersonObject()

        Dim objOrder as New OrderObject()

        DoLogging( objPerson )

        DoLogging( objOrder )

    End Sub

    Sub DoLogging( loggable as ILoggable )

        loggable.LogState()

    End Sub

 

Our DoLogging method accepts anything implementing the ILoggable interface and invokes the LogState method.  The DoLogging method is where Interfaces create the ability to reuse code – that is, our sub procedure can contain specific code for acting on the ILoggable interface and we don’t have to add the code into each class that implements ILoggable.  Granted, this is a trivial example, but it’s a very powerful mechanism.  Our Person and Order objects adhere to the ILoggable contract (interfaces are really contracts enforced by the CLR) allowing us to program other objects against the contract instead of the specific objects themselves; this, in turn, allows us to separate our object layers from one another instead of closely coupling all our objects together into a monolithic spaghetti of object relationships.  I implement interfaces much more than I program inheritance models for many reasons, including the following:

-Interfaces help me identify the intersections of objects in code, which helps me design a more robust solution.

-Interfaces allow for decoupling of objects (so I don’t need a reference to specific object – I can just reference the Interface type instead).

-Inheritance models must be very carefully designed to actually be reused.  Anticipating future uses of code is tricky, and writing very generic base objects and chaining them together via inheritance is slow going, complex to maintain, and often unsuccessful anyway.  Determining a contract for behaviour (for example: every ReportObject will provide a method returning a SortedList of Key:Value pairs that my ReportProcessor can interact with …) makes for cleaner design, code and ultimately a higher chance of code reuse.

 

When considering Inherits versus Implements, remember that in the first case you inherit the implementation, and in the second case you agree to the interface contract. 

 

Happy .Netting

posted Wednesday, August 27, 2003 8:02 AM by grant.killian

Strange Interface Behaviour in VB.Net vs. C#

Most of my recent examples have been in VB.Net to benefit the students in my class, but I program more often in C#.  Take the following VB.Net code:

Shared Sub Main()

    dim obj as ILoggable = new PersonObject()

    MessageBox.Show( obj.ToString() )

End Sub

Public Interface ILoggable

    Sub LogState()

End Interface

Public Class PersonObject

    Implements ILoggable

    Public Sub LogState() Implements ILoggable.LogState

        'log Person state to the Person table, text file, whatever

    End Sub

End Class

 

This doesn’t compile in VB.Net because of the obj.ToString() method call. 

 

Now consider the following C# code:

[STAThread]

static void Main()

{

      ILoggable obj = new personObject();

      MessageBox.Show( obj.ToString() );

}

public class personObject: ILoggable

{

      public void LogState()

      {

            //nothing

      }

}

public interface ILoggable

{

      void LogState();

}

 

Fasten your seat belts, the C# compiles and runs; it displays “personObject” in the dialogbox when MessageBox.Show( obj.ToString() ) is called.  C# Interfaces behave as if they derive from System.Object, while VB.Net interfaces do not.  Where is the interoperability?  Yikes.  This makes Interfaces in C# more powerful since you can interrogate via Reflection. Try:

MessageBox.Show( obj.GetType().ToString() );

 

And you’ll see what I’m getting at (it displays the type name personObject).

 

Score 1 (maybe 2, if you’ve created an elaborate reflection-dependent design) for C#.  Anyone have any insight into why this is?

posted Wednesday, August 27, 2003 7:57 AM by grant.killian




Powered by Dot Net Junkies, by Telligent Systems