Interface and inheritance usage

Inheritance is one of the basic concepts of OO, using class inheritance yoy can define a chain of classes from the base class, the more generic and less functional, down to the derived classes specialized with more added functionalities. This chain can be seen as a list of classes then are related between them through a ‘is a’ relationships;

Ex an Employee is a Person that is Human Being that is a Creature.

Together with ‘is a relationship’ you can relate classes using a so called ‘has a’ relationship, to define a compositemodel;

Ex a Car has an Engine, it has some Wheels

It’s important to use the right relationship when build the class structure, otherwise it would be necessary change the classes definition and refactor previous code that was using the classes definition in the meantime (a pain usually, specially because the domain class are often in class library shared among several projects….)

Sometimes this relations are not enough to define the class structure so you can use the Interfaces; the interface is a contract between classes that implement an interface and classes that uses them; the interface define the ‘can do’ relationship. This let us to define what are the capabilities that the class will be able to do… in this meaning it’s a contract.

Ex a Electric Plug defines a contract, only the Appliances implementing the contract can be plugged, otherwise it will not work.

So when to use Hierarchies and when Interfaces?

The rule is basically when some classes are in ‘is a’ or ‘has a’ use the first, when you want to expose some contract/’can do’ between object that are not of the same families but able to do same things (even implemented in totally different ways) use the second.

In you start defining an Abstract base class with several classes that derive from this and you end up with no shared code at all, because all the classes are natural very different use the Interface, hierarchy derivation make sense when you need to specialize some aspects or your derived classes through method overriding or adding new methods, but anyway some code is shared and reused…

Ex

We want to define an utility to compress/decompress files using zip/7-zip and rar formats; the base class can be a general compressor, with an interface that will define the ‘can do’ action of a compressor class and an inheritance between zip and 7-zip classes as they are related, but it does not make sense to derive the rar format because it’s a totally different in the approach to compress file contents


using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.IO;

namespace compressor
 {
 public class CompressedFile
 {
 public long OriginalSize { get; set; }
 public long CompressedSize { get; set; }
 // ...
 }

public abstract class FileCompressor
 {
 /// <summary>
 /// it counts the files with 0 compression
 /// </summary>
 /// <returns>number of them</returns>
 /// <remarks>it's shared among implementation</remarks>
 public int CountStored()
 {
 IEnumerable<CompressedFile> names = from compressedFile in CompressedFiles
 where compressedFile.CompressedSize == compressedFile.OriginalSize
 select compressedFile;

return names.Count<CompressedFile>();
 }

/// <summary>
 /// Info about implemented algorithm
 /// </summary>
 /// <returns>txt with implemented algoritm info</returns>
 public abstract string GetAlgorithmInfo();

/// <summary>
 /// List of compressed files, property
 /// </summary>
 IEnumerable<CompressedFile> CompressedFiles { get; set; } //has-a
 }

/// <summary>
 /// contract
 /// </summary>
 public interface IFileCompressor
 {
 /// <summary>
 /// Compres files
 /// </summary>
 void Compress();
 /// <summary>
 /// Extract compressed info
 /// </summary>
 void Extract();
 }

public class ZipFileCompress : FileCompressor, IFileCompressor //is a, can do
 {

public void Compress()
 {
 // ...
 }

public void Extract()
 {
 // ...
 }

public override string GetAlgorithmInfo()
 {
 return "[ZIP]"; //specialization
 }
 }

/// <summary>
 /// Zip implementation
 /// </summary>
 public class SevenZipFileCompress : ZipFileCompress
 {
 public override string GetAlgorithmInfo()
 {
 return "[7-ZIP]";
 }
 }

/// <summary>
 /// Rar implementation
 /// </summary>
 public class RarFileCompress : FileCompressor, IFileCompressor
 {

public void Compress()
 {
 // ...
 }

public void Extract()
 {
 // ...
 }

public override string GetAlgorithmInfo()
 {
 return "[RAR]";
 }
 }

/// <summary>
 /// MAIN
 /// </summary>
 class Program
 {
 static void ExecCompression(FileCompressor fc)
 {
 Console.WriteLine(string.Format(" Executing...{0}", fc.GetAlgorithmInfo()));
 // ...
 }
 static void Main(string[] args)
 {
 IFileCompressor zipFileCompressor = new ZipFileCompress();
 IFileCompressor rarFileCompressor = new RarFileCompress();

ExecCompression(zipFileCompressor as ZipFileCompress);
 ExecCompression(rarFileCompressor as RarFileCompress);
 //...
 }
 }
 }

2011-07-15 094948

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s