instancing. For example - if you are writing a container class that will hold a polymorph collection of elements - you may want to have a virtual class function that return the default class type used to instance new elements in the container, instead of just instancing the base element class. Doing so will allow descendant classes make reliable assumptions about the safety of typecasting within the extended methods in the descendant container class.unit BasicClass;interfacetype TElementClass = class of TBaseElement; TBaseElement = class(TObject) end; TBaseContainer = class(TObject) class function ElementClass:TElementClass; virtual; function ValidElement(anElement:TBaseElement):Boolean; end;implementation{ TBaseContainer }class function TBaseContainer.ElementClass: TElementClass;begin Result := TBaseElement;end;function TBaseContainer.ValidElement(anElement: TBaseElement): Boolean;begin Result := anElement is ElementClass;end;end."But..." - you will say; "you can just override methods in the descendant class for the same effect?". Yes, you can and it works well when you add new functionality, but what about functionality that already has been implemented in class higher in your inheritance tree? unit AdvancedClass;interfaceuses BasicClass;type TAdvancedElement = class (TBaseElement) end; TAdvancedContainer = class(TBaseContainer) class function ElementClass:TElementClass; override; end;implementation{ TAdvancedContainer }class function TAdvancedContainer.ElementClass: TElementClass;begin Result := TAdvancedElement;end;end.The base class won't have an understanding of it's descendants, so if you want it to be able to work with content from descendant classes, you would either have to override/redo the functionality or - do as above - allow the base class to work with their own child classes as well.program ExtendableClasses;{$APPTYPE CONSOLE}uses SysUtils, BasicClass in 'BasicClass.pas', AdvancedClass in 'AdvancedClass.pas';procedure Main;var Element1, Element2 : TBaseElement; Container1, Container2 : TBaseContainer;begin Container1 := TBaseContainer.Create; Container2 := TAdvancedContainer.Create; Element1 := Container1.ElementClass.Create; Element2 := Container2.ElementClass.Create; Writeln('E1: ', Element1.ClassName); Writeln('E2: ', Element2.ClassName); Writeln('E1 valid in C1: ', Container1.ValidElement(Element1)); Writeln('E2 valid in C1: ', Container1.ValidElement(Element2)); Writeln('E1 valid in C2: ', Container2.ValidElement(Element1)); Writeln('E2 valid in C2: ', Container2.ValidElement(Element2));end;begin try try Main; except on E:Exception do Writeln(E.Classname, ': ', E.Message); end; finally Write('Press Enter: '); Readln; end;end.This particularly goes for dialogs and forms that use a polymorph class - make a virtual class function to enable overriding the class instancing. Avoid the rigidly defined TSomeInheritableClass.Create constructs and call the virtual class type function instead. Note on constructorsWhen I finally "got" OOP as opposed to structured programming, it was hard to drop the structured way of thinking when it came to instancing. Most of my classes would only have a constructor that took a ton of parameters to save a few lines at the point of instancing that class. While this might work well for monomorphic classes, it really will not be good for a class hierarchy, and it took me some time to get to the habit of having a parameterless Create. Today, I almost wish for a compiler hint if I should happen to write constructors that require parameters.Hide detail with LayersThink in APIs and layers and try to propagate only content between the layers, and not details that are specific to connectivity, storage, etc. A good layered design will allow you to rip out and replace parts of the architecture without massive rewrites. When you design your APIs or layers, you should consider leaving space or hooks for piggybacking