PDA

View Full Version : Property Reintroduce



مصطفی ساتکی
یک شنبه 27 تیر 1389, 09:21 صبح
سلام به تعريف كلاس هاي زير نگاه كنيد.براينكه Media رو تو كلاس هاي ClassA ,‍ClassB مجدداً تعريف نكنم چه راهي پيشنهاد مي ديد.تعريف كنم جايگزين بشه اينطوري خصيصه مشابه در كلاس بالاتر هم داره منابع اشغال مي كنه كه بايستي Free بشه.

unit Unit4;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
tMedia= Class
private
public
Msg : string;
Constructor Create;virtual;
End;
tMediaA= Class(tMedia)
public
Constructor Create;override;
End;
tMediaB= Class(tMedia)
public
Constructor Create;override;
End;

Tbase = Class(TComponent)
private
FMedia : tMedia;
public

property Media : tMedia read FMedia;
constructor Create(AOwner : TComponent);override;
End;
TClassA = Class(Tbase)
private
FMedia : tMediaA;
public
property Media : tMediaA read FMedia;
constructor Create(AOwner : TComponent);override;
End;

TClassB = Class(Tbase)
private
FMedia : tMediaB;

public
property Media : tMediaB read FMedia;
constructor Create(AOwner : TComponent);override;

End;

TForm4 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.Button1Click(Sender: TObject);
var a : TClassB;
begin
a := TClassB.Create(Self);
ShowMessage(a.Media.Msg);
end;

procedure TForm4.FormCreate(Sender: TObject);
begin

end;

{ tMediaB }

constructor tMediaB.Create;
begin
inherited;
Msg := 'MediaB';
end;

{ tMedia }

constructor tMedia.Create;
begin
Msg := 'Media';
end;

{ tMediaA }

constructor tMediaA.Create;
begin
inherited;
Msg := 'MediaA';
end;

{ Tbase }

constructor Tbase.Create(AOwner: TComponent);
begin
inherited;
FMedia := tMedia.Create;
end;

{ TClassA }

constructor TClassA.Create(AOwner: TComponent);
begin
inherited;
if Assigned(FMedia) then
begin
FMedia.Free;
FMedia := nil;

end;
FMedia := tMediaA.Create;
end;

{ TClassB }

constructor TClassB.Create(AOwner: TComponent);
begin
inherited;
if Assigned(FMedia) then
begin
FMedia.Free;
FMedia := nil;
end;
FMedia := tMediaB.Create;
end;

end.

vcldeveloper
یک شنبه 27 تیر 1389, 13:49 عصر
می تونید به شکل زیر عمل کنید:

unit Unit4;

interface

uses
SysUtils, Classes;

type
TMedia = Class
private
public
Msg: string;
Constructor Create; virtual;
End;

TMediaA = Class(TMedia)
public
Constructor Create; override;
End;

TMediaB = Class(TMedia)
public
Constructor Create; override;
End;

TMediaClass = class of TMedia;

Tbase = Class(TComponent)
private
FMedia: TMedia;
FMediaClass: TMediaClass;
protected
function GetMedia: TMedia; virtual;
property MediaClass: TMediaClass read FMediaClass write FMediaClass;
public
property Media: TMedia read GetMedia;
constructor Create(AOwner: TComponent); override;
End;

TClassA = Class(Tbase)
public
constructor Create(AOwner: TComponent); override;
End;

TClassB = Class(Tbase)
public
constructor Create(AOwner: TComponent); override;
End;

implementation

{ tMedia }

constructor TMedia.Create;
begin
Msg := 'Media';
end;

{ tMediaA }

constructor TMediaA.Create;
begin
inherited;
Msg := 'MediaA';
end;

{ tMediaB }

constructor TMediaB.Create;
begin
inherited;
Msg := 'MediaB';
end;

{ Tbase }

constructor Tbase.Create(AOwner: TComponent);
begin
inherited;
MediaClass := TMedia;
end;

destructor Tbase.Destroy;
begin
FMedia.Free;
inherited;
end;

function Tbase.GetMedia: TMedia;
begin
if not Assigned(FMedia) then
FMedia := FMediaClass.Create;
Result := FMedia;
end;

{ TClassA }

constructor TClassA.Create(AOwner: TComponent);
begin
inherited;
MediaClass := TMediaA;
end;

{ TClassB }

constructor TClassB.Create(AOwner: TComponent);
begin
inherited;
MediaClass := TMediaB;
end;

end.

در این حالت، هر کلاس جدیدی که از TBase مشتق میشه، فقط باید نوع کلاس Media مورد نظرش رو از طریق مقدار دادن به خصوصیت MediaClass مشخص کنه. در متد GetMedia، اگر شی ایی از نوع مربوطه ساخته نشده باشه، شی مربوطه ساخته میشه، و فیلد FMedia به اون شی اشاره خواهد کرد. در این حالت، ساخت شی، و نگهداری اشیاء مربوطه بر عهده کلاس والد هست، و کلاس های فرزند این داده ها را نگهداری نمی کنند.

نمودار کلاس هایتان قبل از این تغییرات به این شکل هست:

53093

و بعد از اعمال تغییرات فوق، به این شکل تبدیل میشه:

53094


البته یک راه دیگه این هست که شما فیلد FMedia را در کلاس TBase به صورت protected تعریف کنید، و خصوصیت Media هم به این فیلد اشاره کنه، و هر کلاس در متد Create خودش، یک نمونه شی از کلاس مورد نظرش بسازه و به FMedia اختصاص بده. البته در این حال، کلاس TBase خودش نباید در متد Create خودش شی ایی را به FMedia اختصاص بده، و فقط کلاس های فرزند باید این کار را بکنند، تا مجبور نشید قبل از ایجاد شی جدید، شی ساخته شده در کلاس والد را آزاد کنید.