Interface Contract Question

  • Thread starter Thread starter Jeff Gilbert
  • Start date Start date
J

Jeff Gilbert

Hello, I would appreciate some input to the following question of "proper"
design (if such a thing exists).

I'm implementing a reporting subsystem for the project I'm currently working
on. I handle the display of the reports via a DeliveryEngine object that is
implemented like so:

IDeliveryEngine (interface)
|
|
DeliveryEngineBase (mustinherit)
|
|
PreviewEngine (final implementation)

I have a property set up called Target. It defines the place where the
reports are to be delivered. For the PreviewEngine it is the form that
contains the viewer control. For the PrintEngine, it is the printer's name.
In the interface it is declared as type "Object". However, each
implementation can take a different type of Target for obvious reasons. To
maintain type safety I want to shadow the Target property and re-declare its
type to the specific type each implementation needs.

For example, whereas the interface's Target property is of type "Object", I
would like to declare the PreviewEngine's Target property as type "Form":

Shadows Property Target as Form

The problem obviously is that this will break the original interface
contract, but its the only way to maintain type safety for my
implementations...and I feel this is a situation where it makes sense to
break the contract - each implementation is different. However, I need to be
able to handle each of the implementations as the same type of object. Can
anyone give me some advice? Thanks!

Jeff Gilbert
 
Jeff,
I take it this is a VB.NET question?

Rather then shadowing the base class, I would implement the interface method
as hidden (private or protected) with a public one of the correct type in
the derived classes. The loosely typed property would make use of the
strongly typed ones...

Alternatively I would define an ITarget interface that the Target returns,
then each derived class would offer an object that implements this
interface, which means that PrintEngine could not return a string, it would
need to return a String Proxy. The ITarget interface would have all the
methods & subs that are required of a Target. However this second method may
be more work, although I suspect more correct. "Correctness" is good!

Something like:

' First method
Public Interface IDeliveryEngine
Property Target As Object
End Interface

Public MustInherit Class DeliveryEngineBase
Implements IDeliveryEngine

Protected MustOverride Property IDeliveryEngine_Target As Object _
Implements IDeliveryEngine.Target

End Class

Public Class PreviewEngine
Inherits DeliveryEngineBase

Protected Overrides Property IDeliveryEngine_Target As Object
Get
Return Target
End Get
Set(ByVal value As Object)
Target = DirectCast(value, Form)
End Set
End Property

Public Property Target As Form

End Class

Public Class PrintEngine
Inherits DeliveryEngineBase

Protected Overrides Property IDeliveryEngine_Target As Object
Get
Return Target
End Get
Set(ByVal value As Object)
Target = DirectCast(value, String)
End Set
End Property

Public Property Target As String

End Class


' Second method
Public Interface ITarget
' methods that an target is expected to implement!
End Interface

Public Interface IDeliveryEngine
Property Target As ITarget
End Interface

Public MustInherit Class DeliveryEngineBase
Implements IDeliveryEngine

Private m_target as ITarget

Public Property Target As ITarget Implements IDeliveryEngine.Target
Get
Return m_target
End Get
Set(ByVal value As Object)
m_target = value
End Set
End Property

End Class

Public Class PreviewEngine
Inherits DeliveryEngineBase

End Class

Public Class PrintEngine
Inherits DeliveryEngineBase

End Class

Hope this helps
Jay
 
Back
Top