CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Grant Killian's Blog

No, this has nothing to do with beer -- but maybe it should?

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



Comments

Pure OO Fundamentalist (POOF) said:

RIDICULOUS! If mere 'interface inheritance' is allowed to 'count' as OO, then even Visual Basic 5.0 and 6.0 could be considered OOPLs! Clearly this is considered heresy, apostasy, heterodoxy, anathema, abomination, Evil, Bad, and Wrong. Implementation inheritance must be paramount, or you open the door to admitting that, horror of horrors, even VB 4.0 could support dynamic polymorphism through the use of evil weakly-typed Object references, or, the ultimate insult, VB 1/2/3 via (mis-)using its Form references. No, the Great VB Unwashed must never be allowed a seat at the OO table. The three rules of OO must forevermore remain,

1) Identity

2) Polymorphism via Inheritance

3) IMPLEMENTATION Inheritance

For further safety, object identity and polymorphism obviously need to be redefined in such a way as to totally excommunicate Visual Basic.

BTW, encapsulation is deprecated. Since implementation inheritance and methods break encapsulation, encapsulation must therefore be irrelevant.

# February 19, 2004 11:48 AM

TrackBack said:

# March 18, 2005 11:44 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!