PDA

View Full Version : چرا نمیشه یه همچین interface رو طراحی کرد؟



مهدی فهمیده غلامی
چهارشنبه 28 اردیبهشت 1384, 23:30 عصر
کد زیر را در نظر بگیرید:


Isum = interface
['{66C1649F-9281-4B5A-A558-734A40971403}']
function Add :pointer;virtual;
end;

و بعد کلاس هایی که هر کدوم پیاده سازی خاص Isum را انجام می دن:

این :


SumClass1=class(TInterfacedObject,Isum)
function Add(x,y:integer):integer;overload;

و این:
[/code]
SumClass2=class(TInterfacedObject,Isum)
function Add(x,y:real):real;overload;
[/code]
مشکل اینجاست که همچین تعریفی در دلفی مجاز نیست و من حتما یه چنین پیاده سازی رو می خوام.
در ضمن در خود interface Isum از وجود کلمه virtual خطا میگیره.
چه باید کرد؟

vcldeveloper
پنج شنبه 29 اردیبهشت 1384, 05:06 صبح
در ضمن در خود interface Isum از وجود کلمه virtual خطا میگیره.
استفاده از متد virtual در Interface بی معنی هست!


مشکل اینجاست که همچین تعریفی در دلفی مجاز نیست و من حتما یه چنین پیاده سازی رو می خوام.
متد Add در کد زیر توسط IMyInterface تعریف شده و توسط TMyClass1 (برای نوع string) و TMyClass2(نوع integer) پیاده سازی شده. تعداد پارامترهای ورودی و نوع آنها و نوع پارامتر خروجی نامشخص هست:


interface

type
IMyInterface = interface
procedure Add(Args: array of const; var Output: variant);
end;

TMyClass1 = class(TInterfacedObject,IMyInterface)
//Aggrigate some string variables
procedure Add(Data: array of const; var Output: variant);
end;

TMyClass2 = class(TInterfacedObject,IMyInterface)
//Add some integer numbers
procedure Add(Data: array of const; var Output: variant);
end;

implementation

{ TMyClass1 }
procedure TMyClass1.Add(Data: array of const; var Output: variant);
var
i : integer;
begin
try
for i := 0 to High(Data) do
case Data[i].VType of
vtAnsiString : Output := Output + string(Data[i].vAnsiString);
vtChar : Output := Output + Data[i].VChar;
end; //case
except
Output := '';
end;
end;

{ TMyClass2 }
procedure TMyClass2.Add(Data: array of const; var Output: variant);
var
i : integer;
begin
try
for i := 0 to High(Data) do
Output := Output + Data[i].VInteger;
except
Output := -1;
end;
end;


مثال:


procedure TForm1.Button1Click(Sender: TObject);
var
Output : variant;
MyClass1 : IMyInterface;
begin
MyClass1 := TMyClass1.Create;
MyClass1.Add(['a','b','cj','0'],Output);
ShowMessage(Output);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
Output : variant;
MyClass2 : IMyInterface;
begin
MyClass2 := TMyClass2.Create;
MyClass2.Add([1,2,3,4,5],Output);
ShowMessage(IntToStr(integer(Output)));
end;

مهدی فهمیده غلامی
پنج شنبه 29 اردیبهشت 1384, 21:59 عصر
اقای کشاورز سپاسگزارم.
این واقعا همون چیزی بود که می خواستم. :D :D :D

مهدی فهمیده غلامی
پنج شنبه 29 اردیبهشت 1384, 22:42 عصر
یک مشکل :دلفی vreal نداره
چطوری میشه عمل جمع اعداد اعشاری رو پیدا سازی کرد
من کد بالا رو میخوام برای اعداد اعشاری توسعه بدم
ولی یه چیزی مثل <<<<VReal>>>>نیاز که دلفی اونو نداره !
حالا باید چکار کرد؟؟؟

مهدی فهمیده غلامی
پنج شنبه 29 اردیبهشت 1384, 23:23 عصر
چرا از IMyInterface یک شی ساخته شده:


MyClass2 : IMyInterface;

vcldeveloper
جمعه 30 اردیبهشت 1384, 01:46 صبح
یک مشکل :دلفی vreal نداره
می تونید از vExtended یا vCurrency استفاده کنید. البته حافظه بیشتری از real استفاده می کنند.


چرا از IMyInterface یک شی ساخته شده:
اینطوری می تونید از قابلیت refrence-counting اون interface استفاده کنید. یعنی بعد از اینکه کارتون با شی مورد نظر تموم شد، لازم نیست اونو free کنید. در صورتی که ارجاعی (refrence) به اون وجود نداشته باشه، بطور اتوماتیک پاک سازی میشه.

مهدی فهمیده غلامی
جمعه 30 اردیبهشت 1384, 12:22 عصر
من متوجه نمیشم در اینجا واقعا چه اتفاقی داره میفته؟؟


MyClass2 : IMyInterface;
begin
MyClass2 := TMyClass2.Create;
MyClass2.Add([1,2,3,4,5],Output);
ShowMessage(IntToStr(integer(Output)));

متغیری از نوع IMyInterface تعریف میشه و بعد از کلاس TMyClass2 یک instance ساخته میشه :گیج: :گیج: :گیج:

مهدی فهمیده غلامی
جمعه 30 اردیبهشت 1384, 12:28 عصر
من مستندات دلفی رو بررسی کردم ولی در مورد VInteger و VChar پیدا نکردم
توضیحات بیشتر رو از کجا میشه گیر اورد؟

مهدی فهمیده غلامی
جمعه 30 اردیبهشت 1384, 22:30 عصر
مشکل:من نمی دونم چرا این تیدیل رو run time error می ده؟


for i := 0 to High(Data) do
result := result + Data[i].vcurrency;

حتی نوع vextended رو هم امتحان کردم باز مشکل داره
البته من فکر میکنم Data[i].vcurrency یک اشاره گر باشه.
مشکل چیه؟و چه باید کرد؟

vcldeveloper
شنبه 31 اردیبهشت 1384, 22:16 عصر
حتی نوع vextended رو هم امتحان کردم باز مشکل داره
البته من فکر میکنم Data[i].vcurrency یک اشاره گر باشه.
مشکل چیه؟و چه باید کرد؟
باید به اینصورت بنویسید:


result := result + Data[i].VExtended^;

در ضمن در این حالت داده های ورودی شما باید حتما از نوع اعداد اعشاری یاشند و در صورتی که از اعداد صحیح استفاده کنید، با خطا مواجه میشید. اگر لازم هست که اعداد صحیح و اعشاری با هم استفاده بشند، باید نوع هر ورودی رو با استفاده از Data[i].VType بدست بیارید (همون کاری که در کد بالا برای نوع string و char انجام دادم).



متغیری از نوع IMyInterface تعریف میشه و بعد از کلاس TMyClass2 یک instance ساخته میشه

وقتی متغیری از یک interface تعریف می کنید (IMyInterface)، می تونید از این متغیر برای ایجاد نمونه هایی (Instances) از کلاس هایی که اون Interface رو پیاده سازی کرده اند (TMyClass1 و TMyClass2) استفاده کنید. در این صورت اینترفیس مربوطه بصورت اتوماتیک نمونه ایی از کلاس مورد نظر رو ایجاد میکنه:


var
MyClass2 : IMyInterface;
begin
MyClass2 := TMyClass2.Create;

در کد بالا، هر چند شما نمونه ایی از TMyClass2 بوجود نیاوردید، اما این نمونه بصورت خودکار توسط اینترفیس IMyInterface برای شما ساخته خواهد شد و یک واحد به TMyClass2.RefCount اضافه میشه (RefCount در کلاس TInterfacedObject تعریف شده).
در هنگامی که متغیر مربوطه (در اینجا MyClass2) از محدوده دید (Scope) خارج بشه (در اینجا با خارج شدن از متد Button2Click )، یک واحد از RefCount کم میشه. اگر مقدار RefCount به صفر برسه، شئی اختصاص داده شده به اینترفیس بصورت خودکار توسط اینترفیس پاک سازی میشه و نیازی به فراخوانی متد Free نیست (به این قابلیت Reference-counting گفته میشه).

مهدی فهمیده غلامی
یک شنبه 01 خرداد 1384, 13:31 عصر
با تشکر