TreK
TreK

Reputation: 1174

Understanding the use of Interfaces and Base Classes

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.

Upvotes: 0

Views: 1212

Answers (2)

Imran Rizvi
Imran Rizvi

Reputation: 7438

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.

Upvotes: 0

Thomas
Thomas

Reputation: 3693

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.

Upvotes: 2

Related Questions