Mega Code Archive

 
Categories / Delphi / OOP
 

When use Interfaces, when use Inheritance

Title: When use Interfaces, when use Inheritance ? Question: There are two possibilities to define a (same) class hierarchy: - with interfaces - with inheritance Which one suits your needs Answer: You can fulfill the same operations with interfaces or inheritance as the following shows: IShape = interface procedure paint; end; TSquare = class(TInterfacedObject, IShape) procedure paint; end; TCircle = class(TInterfacedObject, IShape) procedure paint; end; TShape = class procedure paint; virtual; abstract; //procedure makeShape(afigure: TShape); end; TSquare2 = class(TShape) procedure paint; override; end; TCircle2 = class(TShape) procedure paint; override; end; Interfaces are useful when a set of operations, such as rendering or streaming, are used in a broad range of objects. They can reuse code and apply methods to a variety of different applications. Almost the same could have been accomplished by having TSquare2 and TCircle2 descend from TShape which implemented the virtual method Paint. So whats the difference from a point of design? With inheritance you can implement a base behaviour in the base-class like makeShape(), interfaces are pure abstract and dont't allow a real method. You have garbage collection with interfaces and you can handle objects without having to require the object to descend from a particular base class. Even if two classes did not share a commen ancestor, they are assignment compatible with a variabel of IShape: procedure TfrmGen.Button2Click(Sender: TObject); var painter: IShape; painter2: TShape; begin // interface painter:= TSquare.create; painter.paint; painter:= TCircle.create; painter.paint; // inheritance virtual painter2:= TSquare2.create; //painter2.paint; painter2.makeShape(painter2); painter2:= TCircle2.create; painter2.makeShape(painter2); // virtual alternative with painter2.Create do begin makeShape(TSquare2.create); makeShape(TCircle2.create); end; end; A well designed inheritance can be more stable and maintainable in comparison to much runtime objects that implement the same interface. So inheritance has more advantage in a well established design-time hierarchy, interfaces are best in run-time between components. For example we improve a method in a base class, inheritance makes it possible. On the other hand interfaces are more flexible to replace or delegate objects at runtime. For this it's a must do generate a GUID (Globally Unique Identifier) in square brackets. GUID's arent strictly necessary, but if you want to switch between interfaces you'll need them to make QueryInterface work! Now let's compare the advantages between the two Inheritance Interface - big hierarchy - delegation - base behavior - more implemantations of one interface - libraries - run time packages - real time freeing - garbage collection (reference counter) - subclassing - run time flexibility - design time properties - design by contract - fields - properties The most part is the realisation that you cannot mix object references and interface references. Interfaces are reference counted and objects not, so mixing the two approaches gets an access violation. See you at EKON7 in Frankfurt or in my new book "Patterns konkret" ;) // example implementation { TShape } procedure TShape.makeShape(afigure: TShape); begin if afigure NIL then afigure.paint; end; { TSquare2 } procedure TSquare2.paint; begin frmgen.memo1.lines.add('square virtual painted'); end; { TCircle2 } procedure TCircle2.paint; begin frmgen.memo1.lines.add('circle virtual painted'); end; end.