OOP part 3

Tags:    delphi
Skrevet af Bruger #58 @ 16.06.2001
OOP - hvordan og hvorfor, del 3

I denne tredje og sidste del af min OOP serie vil jeg give en forklaring på virtual, override og dynamic, fortælle hvordan man bruger TCollection og -Item og til sidst give nogen generelle tips til når du skriver objektorienteret.

Virtual, override og dynamic

Først: Virtual og dynamic er grundlæggende det samme. Forskellen ligger i, at virtual er optimeret til hastighed og dynamic er optimeret til programstørrelse. Den bedste måde at forklare forskellen på normale og virtuelle metoder er med et eksempel:
type
  TKlasse1 = class(TObject)
  public
    procedure EnProcedure(param: string);
  end;
  TKlasse2 = class(TKlasse1)
  public
    procedure EnProcedure(param: string);
  end;
Her er 2 klasser: TKlasse1 og TKlasse2. Begge har de en public metode med navnet EnProcedure. Hvis jeg nu kører den her kode:
procedure TForm1.FormCreate(Sender: TObject);
var
  klasse1: TKlasse1;
  klasse2: TKlasse2;
begin
  // Opret en TKlasse2 i en variabel af typen TKlasse1
  klasse1 := TKlasse2.Create;
  // Denne linie vil køre TKlasse1.EnProcedure
  klasse1.EnProcedure('Hej med dig!');
  klasse1.Free;
  // Opret en TKlasse2 i en variabel af samme type
  klasse2 := TKlasse2.Create;
  // Denne linie vil køre TKlasse2.EnProcedure
  klasse2.EnProcedure('Hej med dig!');
  klasse2.Free;
end;
Som du kan se, så er der i dette tilfælde forskel på, hvilken type variablen er deklareret som. Hvis vi nu ændrer typedeklarationen af de to klasser:
type
  TKlasse1 = class(TObject)
  public
    procedure EnProcedure(param: string); virtual;
  end;
  TKlasse2 = class(TKlasse1)
  public
    procedure EnProcedure(param: string); override;
  end;
Så vil koden nu se sådan ud:
procedure TForm1.FormCreate(Sender: TObject);
var
  klasse1: TKlasse1;
  klasse2: TKlasse2;
begin
  // Opret en TKlasse2 i en variabel af typen TKlasse1
  klasse1 := TKlasse2.Create;
  // Denne linie vil køre TKlasse2.EnProcedure
  klasse1.EnProcedure('Hej med dig!');
  klasse1.Free;
  // Opret en TKlasse2 i en variabel af samme type
  klasse2 := TKlasse2.Create;
  // Denne linie vil køre TKlasse2.EnProcedure
  klasse2.EnProcedure('Hej med dig!');
  klasse2.Free;
end;
Nu vil begge metodekald køre TKlasse2.EnProcedure. Det er det man kalder Polymorphisme. Hvis der er noget du ikke forstår, så brug forummet!

TCollection og -Item

TCollection og TCollectionItem er nogen virkelig gode værktøjer når du skal holde styr på en masse objekter af samme type. Nogen gode eksempler på brug af TCollection er f.eks. TCoolBand(s) (Delphi 3 og op, bruges af TCoolBar) og TStatusPanel(s) (vistnok også Delphi 3 og op, bruges af TStatusBar). Her er et kodeskelet du kan bruge, når du skal lave en ny underklasse af TCollection og -Item:
interface

type
  TMinCollectionItem = class(TCollectionItem)
    { Tilføj dine egne deklarationer her }
  end;
  TMinCollection = class(TCollection)
  private
    function GetItem(Index: Integer): TMinCollectionItem;
    procedure SetItem(Index: Integer; Value: TMinCollectionItem);
  public
    function Add: TMinCollectionItem;
    constructor Create;
    property Items[Index: Integer]: TMinCollectionItem
     read  GetItem
     write SetItem;
  end;

implementering

function TMinCollection.GetItem(Index: Integer): TMinCollectionItem;
begin
  Result := TMinCollectionItem(inherited GetItem(Index));
end;

procedure TMinCollection.SetItem(Index: Integer; Value: TMinCollectionItem);
begin
  inherited SetItem(Index, Value);
end;

function TMinCollection.Add; TMinCollectionItem;
begin
  Result := TMinCollectionItem(inherited Add);
end;

constructor TMinCollection.Create;
begin
  inherited Create(TMinCollectionItem);
end;
Det er hvad der skal til. Bemærk at noget af koden muligvis er forkert (jeg har ikke Delphi åben mens jeg skriver det her) og at der mangler kode til Insert metoden i TMinCollectionItem. Prøv at se om du kan gætte dig til hvordan den skal se ud!

Generelle tips

Der er en del ting du skal tænke på, når du skriver OO.

Nummer et: Koden skal kunne genbruges! Det nytter ikke noget, at du har brugt dage på at skrive et objekt og få det integreret i dit program, da du opdager at du hellere vil kalde TForm1 for THovedForm, og der så står TForm1 overalt i dit objekt (f.eks. hvis du skal ændre noget på en label). I sådanne tilfælde skal du bruge events. Kort sagt: Koden skal være uafhængig.

Nummer to: Læg altid koden til et objekt i en separat .PAS fil. Det gør det meget nemmere, hvis du opdager at du kan bruge koden i et andet program. Så kan du bare kopiere .PAS filen (eller lægge den et centralt sted) i stedet for at inkludere en TForm1 i et projekt hvor den slet ikke hører til. Det gør det også meget nemmere at distribuerer koden til andre og overholde det første bud.

Nummer tre: Det her gælder faktisk programmering generelt. Koden skal være læsbar. Tænk på, hvis du nu snubler over koden om tre år, og du ikke kan forstå hvorfor du nu har skrevet det og det på den og den måde. Objektnavne og metodenavne skal give mening. Du skal altså ikke kalde en metode CoolFyr, men hellere GemTilFil. Det giver meget mere mening. Sørg også for at putte kommentarer i din kode. Men ikke for mange!

Nummer fire: Brug altid de rigtige "fortegn". Alle objektnavne osv. (typer) skal starte med T (et stort T). Alle feltvariabler (normalt variabler der bruges til at gemme en værdi af et property og ligger i private sektionen) skal starte med et stort F. Alle metoder der bruges til af hente og gemme værdien af et property skal starte med hhv. Get og Set. Se eventuelt på andres kode.

Det var alt for denne gang. Som sagt var det her sidste del i OOP serien, så det vil jeg ikke skrive mere om. Se nu og kom ud og skriv nogen kvalitetsprogrammer.


Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (0)

Du skal være logget ind for at skrive en kommentar.
t