0

I know there are a number of post out there on Interfaces and Base classes, but I'm having a hard time getting the correct design pattern understanding.

If I were to write a reporting class, my initial though would be to create an interface with the core properties, methods, etc. that all reports will implement.

For example:

Public Interface IReportSales

Property Sales() As List(Of Sales)
Property ItemTotalSales() As Decimal

End Interface

Public Interface IReportProducts

Property Productss() As List(Of Inventory)
Property ProductsTotal() As Decimal

End Interface

Then I assume I would have a class to implement the interface:

Public Class MyReport
Implements IReportSales


Public Property Sales() As System.Collections.Generic.List(Of Decimal) Implements IReportItem.Sales
    Get
        Return Sales
    End Get
    Set(ByVal value As System.Collections.Generic.List(Of Decimal))
        Items = value
    End Set
End Property

Public Function ItemTotalSales() As Decimal Implements IReport.ItemTotalSales
    Dim total As Decimal = 0.0
    For Each item In Me.Sales
        total = total + item
    Next
End Function

End Class

My thought was that it should be an interface because other reports may not use "Items", this way I can implement the objects that are used for a given report class.

Am I way off? should I have still have just created a base class? My logic behind not creating a base class was that not all report classes may use "Items" so I didn't want to define them where they are not being used.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
TreK
  • 1,144
  • 2
  • 13
  • 25
  • Can you explain the reason for implementing the interface here? Don't you think, it's giving memory unnecessarily. I can do it without interface. Right? – Pankaj Apr 19 '12 at 18:17
  • Your question is a bit confusing to me. You're worried about implementing more reports that don't use `Items`? You have that defined in your interface as a requirement though. As it stands currently any class that you wish to implement `IReport` will have to supply an `Items()` property and an `ItemTotalSales()` function. – Thomas Apr 19 '12 at 18:17
  • Just because you implement an interface that contains Items doesn't mean that you need to use it. – Xaisoft Apr 19 '12 at 18:24
  • @Guest: Implementing an interface only means that you're providing an implementation for whatever *functions* or *properties* it specifies. The amount of space taken up by the implementation depends on the implementation, not on the interface. – Mike Bailey Apr 19 '12 at 18:29
  • I guess my main question is this a valid scenario for using an interface? – TreK Apr 19 '12 at 18:31
  • @MikeBantebui - What exactly is the need to introduce interface? Why can't you just put the method definition directly? – Pankaj Apr 19 '12 at 18:31
  • do you mean Abstract in second last paragraph? – Imran Rizvi Apr 19 '12 at 18:56

2 Answers2

2

To attempt to answer you question, abstract classes are used to provide a common ancestor for related classes. An example of this in the .Net API is TextWriter. This class provides a common ancestor all various classes whose purpose is to write text in some fashion.

Interfaces are more properly used to act as adapters for different objects that don't belong in the same "family" of objects but have similar capabilities. A good example of this can be seen with the various collections in the .Net API.

For example, the List and Dictionary classes provide the ability for you to manage a collection of objects. They do not share a common ancestor by inheritance, this wouldn't make sense. In order to allow easy interop between them though, they implement some of the same interfaces.

Both classes implement IEnumerable. This cleanly allows you use objects of either type List or Dictionary as an operand for anything that requires an IEnumerable. How wonderful!

So now in your case in designing new software you want to think about how this would fit into your problem space. If you give these classes a common ancestor via inheritance of an abstract class you have to be sure that all the items that inherit from it are truly of the base type. (A StreamWriter is a TextWriter, for example). Inappropriate use of class inheritance can make your API very difficult to build and modify in the future.

Let's say you make an abstract class, ReportBase, for your repots. It may contain a few very generic methods that all reports simply must have. Perhaps it simply specifies the method Run()

You then only have one type of report you want to make so you define a concrete Report class that inherits from ReportBase. Everything is great. Then you find out you need to add several more types of reports, XReport, YReport, and ZReport for sake of example. It doesn't really matter what they are, but they work differently and have different requirements. All of the reports generate pretty HTML output and everyone is happy.

Next week your client says they want XReport and YReport to be able to output PDF documents as well. Now there are many ways to solve this, but obviously adding an OutputPdf method to your abstract class is a poor idea, as some of those reports shouldn't or can't support this behavior!

Now this is where interfaces could be useful to you. Let's say you define a few interfaces IHtmlReport and IPdfReport. Now the report classes that are supposed to support these various output types can implement those interfaces. This will then let you create a function such as CreatePdfReports(IEnumerable<IPdfReport> reports) that can take all reports that implement IPdfReport and do whatever it needs to do with them without caring what the appropriate base type is.

Hopefully this helps, I was kind of shooting from the hip here as I'm not familiar with the problem you're trying to solve.

Thomas
  • 3,603
  • 1
  • 18
  • 23
  • This was great, thanks @Thomas. It's makes complete sense I'm just having a hard time implementing the theory. I appreciate you're time. – TreK Apr 19 '12 at 18:54
  • My biggest suggestion for you would to not get bogged down in trying to over-engineer the solution with a complex class and interface structure if you're not already familiar with the problem space and the issues you're going to have to solve. Write things as you need them and be willing to refactor going forward as you realize it will become beneficial. – Thomas Apr 19 '12 at 18:57
  • @TravisK also don't feel bad about having difficulties. Good design is incredibly hard and almost (or possibly literally) impossible to get right the first time. – Thomas Apr 19 '12 at 19:00
  • Thanks for the encouragement. I been learning it for years, and still trying to get my feet wet. I though maybe I should just jump in and trying at my next chance. Maybe your right and I should look for places to implement through refactoring first. – TreK Apr 19 '12 at 19:15
0

Yes, if you don't know how many reports are not going to use Items , you can go for Abastract class.

Another good thought follows:

You can also create both Interface and Abstract class

Define Sales in Interface , create two abstract classes , one for Reports that implement both and another for Report not implementing Sales. Implement interface for both

define both method (implement sales) in first and only implement sales in second.

Give appropriate names to both Abstract classes e.g. ReportWithItemsBase or ReportWithoutItemsBase.

This way you can also achieve self explaining named base classes on deriving Report classes as well.

Imran Rizvi
  • 7,331
  • 11
  • 57
  • 101