PDA

View Full Version : ساخت تابع در کلاس و طریقه استفاده از آن



sara.mahdavi
یک شنبه 10 شهریور 1392, 14:01 عصر
سلام:لبخندساده:

من میخوام توی یک کلاسی که نوشتم یک تابع تعریف کنم و بعد توی برنامه وقتی اون کلاس رو فراخوانی میکنم بتونم از این کلاس استفاده کنم

امیدوارم منظورم رو رسونده باشم

لطفا به من بگید چطوری این تابع رو ایجاد کنم و توی برنامه چطوری فراخوانیش کنم

با تشکر:چشمک:

یوسف زالی
یک شنبه 10 شهریور 1392, 16:26 عصر
سلام.
توابع در کلاس دو گروه عمده دارند:
1- توابع استاتیک
2- توابع مخصوص شی

برای مثال مورد اول در کلاس TEncoding می تونی مستقیم از توابع درونش استفاده کنی.
برای مثال مورد دوم در کلاس TButton باید یک شی داشته باشی تا بتونی از توش تابع ClientToParent رو صدا بزنی.

نحوه ی ایجاد دومی که کاری نداره، اولی رو توضیح می دم:



TMyClass = class(TSomething)
class procedure P1;
class function F1(x: integer): integer;
end;


کلمه ی کلیدی Class قبل از تابع اون رو بصورت استاتیک تعریف می کنه و می تونید بدون داشتن یک Instance از اون کلاس، ازش استفاده کنید. طبیعیه که نباید از مقادیر حافظه ای شی مربوطه استفاده کنید چون هنوز شیئی ندارید. و ایضا طبیعیه که با داشتن شی از این کلاس، می تونید از طریق همون شی هم به این توابع دسترسی داشته باشید. یک چیزی تو مایه های Constructor ها..

sara.mahdavi
یک شنبه 10 شهریور 1392, 17:18 عصر
ممنون :لبخندساده:
ولی من زیاد متوجه نشدم آخه اطلاعاتم کمه:ناراحت:

سورس این برنامه رو میذارم لطفا یه نگاهی بهش بکنید
داخل سورس گفتم که چه مشکلی دارم

http://mahdavisara.persiangig.com/other/Test%20Class.rar/download

از لطفتون بسیار ممنونم:قلب:

BORHAN TEC
یک شنبه 10 شهریور 1392, 17:23 عصر
سلام
پیشنهاد می کنم که دروس مربوط به برنامه نویسی شی گرا رو ببینید:
http://www.irstu.com/?p=8490

sara.mahdavi
یک شنبه 10 شهریور 1392, 17:42 عصر
سلام
پیشنهاد می کنم که دروس مربوط به برنامه نویسی شی گرا رو ببینید:
http://www.irstu.com/?p=8490
ممنون از راهنماییتون

حتما این سری آموزش رو نگاه میکنم و ازش استفاده میکنم

ولی اگه در حال حاضر میشد یکم راهنمایی کنید ک چطوری این کار رو بکنم تا برنامه ام تموم شه بعد سر فرصت این مطالب رو یاد میگرفتم بهتر بود

بازم ممنون:چشمک:

Felony
یک شنبه 10 شهریور 1392, 20:03 عصر
مشکلاتی تو کد بود ، من وقت نکردم زیاد تغییرش بدم ، ولی چند تا نکته :

* اول از همه Constructor رو نباید Override میکردی ، زمانی یک متد رو Override میکنن که فقط بخوان عملکردش رو تغییر بدن ، شما علاوه بر تغییر عملکرد تو کدتون داشتید پارامترهای متد رو تغییر میدادید ، بنابراین باید overload ش کنید .

* متد TestCreate رو نباید Private تعریف کنید ، متدهای Private در کلاس های دیگه قابل مشاهده نیستن ، دلیل اینکه میتونید الان ازش استفاده کنید این هست که کلاس TTest شما و کلاس TFrm_Test هر دو در یک کتابخانه قرار دارن و دلفی به این مورد گیر نمیده ، اگر کلاستون رو ببرید تو یک کتابخونه دیگه اونوقت به مشکل میخورید ، برای استفاده از این متد در کلاس های دیگه Scope تعریف متد TestCreate شما public باید باشه .

متدهای معمولی رو نمیتونید به اون روش صدا بزنید ، برای صدا زدن یک متد از یک کلاس اول باید یک نمونه از یک کلاس بسازید ، بعد متد مربوط به نمونه ساخته شده رو صدا بزنید :


var
A: TTest;
begin
A := TTest.Create(Frm_Test, 'TestLabel', 'Question Label', 'Box Hint 0',
'Box Hint 1', 'Box Hint 2', 'Box Hint 3');
A.TestCreate(120);
end;

اگر میخوای متد یک کلاس رو مستقیم و بدونه نمونه سازی ازش صدا بزنی باید متد استاتیک بنویسی ( Class function ) ، همونی که یوسف گفت ...

موفق باشید .

sara.mahdavi
یک شنبه 10 شهریور 1392, 21:24 عصر
خیلی ممنون
ولی این تغییری که شما لطف کردید انجام دادید اون عمل اصلی که کلاس و تابع من باید انجام بده رو انجام نمیده

وقتی تابع رو خارج از کلاس میذارم همه چیز درسته و خوب انجام میشه
ولی می خوام اگه امکانش هست با مقدار دهی توسط تابع به کلاس ، کلاس ساخته بشه و عملیاتش انجام بشه

یوسف زالی
یک شنبه 10 شهریور 1392, 21:34 عصر
//TTest.TestCreate(120); می خوام به این صورت ازش استفاده کنم

یعنی چی؟
الان این شی که درست می شه چطور بهش ارجاع می دی؟
چطور بهش دسترسی داری؟
دقیق بگو چی می خواهی

Ananas
یک شنبه 10 شهریور 1392, 23:31 عصر
var
Frm_Test: TFrm_Test;
testObj : TTest; // یک متغیر از این کلاس تعریف کردیم

implementation

{$R *.dfm}

و بعد:

procedure TFrm_Test.B_1Click(Sender: TObject);
begin
testObj := TTest.Create(Self, 'Reclbl_cp', 'B_Q_cp', 'Box0_Hnt', 'Box1_Hnt', 'Box2_Hnt', 'Box3_Hnt');
testObj.Parent := Self;
testObj.TestCreate(120); // می خوام به این صورت ازش استفاده کنم
end;

sara.mahdavi
دوشنبه 11 شهریور 1392, 09:10 صبح
ببینید توی این مثال 110052

وقتی تابع رو خارج از کلاس تعریف میکنم میتونم ازش استفاده کنم و همه چیز مرتبه

حالا میخوام اگه امکانش هست این تابع توی کلاس تعریف بشه تا نیازی نباشه همیشه این تابع رو تعریف کنم

ممنون:قلب:

یوسف زالی
دوشنبه 11 شهریور 1392, 10:39 صبح
دو تا راه داری:
1- ورود این تابع به یونیتی که کلاس توشه
2- نوشتن تابع استاتیک

طی توضیحی که قبلا دادم:


TFrm_Test = class(TForm)
B_1: TButton;
procedure B_1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure TestCreate (Question :integer); // <<== اینجا تابع رو تعریف کردم البته نمیدونم درسته یا نه
procedure LNextPage_Click(Sender: TObject);
procedure LPrivPage_Click(Sender: TObject);
end;

می شه:


TFrm_Test = class(TForm)
B_1: TButton;
procedure B_1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
class procedure TestCreate (Question :integer); // <<== اینجا تابع رو تعریف کردم البته نمیدونم درسته یا نه
procedure LNextPage_Click(Sender: TObject);
procedure LPrivPage_Click(Sender: TObject);
end;

فکر کنم اصلا دقت نکردید :متفکر:

sara.mahdavi
دوشنبه 11 شهریور 1392, 12:53 عصر
چرا آقا یوسف دقت کردم ولی منظورتون رو متوجه نمیشم چون اطلاعاتم دراین باره کمه:ناراحت:

فک کنم بهتر باشه اول برم همنوطور که آقای Object Pascal (http://barnamenevis.org/member.php?75214-Object-Pascal) گفتند در مورد کلاس و توابع بیشتر بخونم

بازم ممنونم ازتون :لبخندساده:

sara.mahdavi
دوشنبه 11 شهریور 1392, 20:11 عصر
من تموم این آموزش های مخصوص برنامه نویسی شی گرا رو نگاه کردم و مطالب خوبی فهمیدم

ولی من توی برنامم با استفاده از تابع میخوام کلاسم رو بسازم یعنی Create کردن داخل تابع اتفاق میوفته و حالا نمیدونم این کار درست هست یا نه

من فکر میکنم این کد



var
A: TTest;
begin
A := TTest.Create(Frm_Test, 'TestLabel', 'Question Label', 'Box Hint 0',
'Box Hint 1', 'Box Hint 2', 'Box Hint 3');
A.TestCreate(120);
end;




یکبار کلاس Test رو میسازه با حالتی که من نمیخوام اتفاق بیوفته.
درصورتی که حالت درست ساخت شدن کلاس توی تابع اتفاق میوفته

اگه لطف کنید و این Test Class 2.rar (http://barnamenevis.org/attachment.php?attachmentid=110052&d=1378098585) مثال رو ببینید
من دقیقا میخوام همین اتفاق توی کلاسم بیوفته
لطفا درصورت کد رو تغییر بدید
واقعا ممنون میشم

Ananas
سه شنبه 12 شهریور 1392, 03:30 صبح
یک مثال مشابه:

TTestClass = class(TForm)
Parent : TWinControl;
Name : string;
constructor Create(_name: string; _parent: TWinControl);
end;

حالا یک تابع مستقل تعریف میکنم که خروجی تابع اشاره گری باشه به کلاس:

function CreateTestClass(_parent: TWinControl):TTestClass;
begin
Result := TTestClass.Create('mohammad', _parent);
end;

تعریفه یک متغیر:

var
Form1: TForm1;
test : TTestClass;

و صدا زدنه تابع:

begin
test := CreateTestClass(Self);
end;

sara.mahdavi
سه شنبه 12 شهریور 1392, 15:39 عصر
ممنون
ولی باز هم مشکل دارم :عصبانی++:
واقعا نمی دونم باید چکار کنم کلا قاطی کردم

لطفا اگه امکانش هست روی همین مثال خودم توضیح بدید
یا لطف کنید همونطوری که درسته تغییرش بدید تا بصورت کامل شده و عملی بفهمم باید چیکار کنم

بازم ممنون:افسرده:

BORHAN TEC
سه شنبه 12 شهریور 1392, 17:52 عصر
سلام
من 10 شهریور به شما لینک دادم و الان 12 شهریور است. اگه اون فیلم ها رو دیده بودید تا الان مشکلتون حل میشد. من این تاپیک رو نخوندم ولی اگه منظورتون اینه که بدون ایجاد Instance از کلاس از توابع داخلش استفاده کنید میتونید فیلم برنامه نویسی شی گرا در دلفی(بخش هشتم : نکات پراکنده در برنامه نویسی شی گرا در دلفی) رو از آدرس زیر دریافت کرده و تماشا کنید:
http://www.irstu.com/?p=8490

sara.mahdavi
سه شنبه 12 شهریور 1392, 18:36 عصر
سلام
من 10 شهریور به شما لینک دادم و الان 12 شهریور است. اگه اون فیلم ها رو دیده بودید تا الان مشکلتون حل میشد. من این تاپیک رو نخوندم ولی اگه منظورتون اینه که بدون ایجاد Instance از کلاس از توابع داخلش استفاده کنید میتونید فیلم برنامه نویسی شی گرا در دلفی(بخش هشتم : نکات پراکنده در برنامه نویسی شی گرا در دلفی) رو از آدرس زیر دریافت کرده و تماشا کنید:
http://www.irstu.com/?p=8490
من تمام اون بخشهایی که مربوط به برنامه نویسی شی گرا بود دیدم ولی بصورت عملی دقیق نمیفهمم که چطوری این کاری که میخوام رو انجام بدم و روش صحیحش رو چون تا حالا کار نکردم نمیدونم:ناراحت:

یوسف زالی
سه شنبه 12 شهریور 1392, 23:24 عصر
من بصورت عملی دقیق نمی فهمم شما چی می خواهی :چشمک:
یک بار دقیق تعریف کن چه انتظاری داری از برنامه، تا ببینیم چی می شه.

Ananas
چهارشنبه 13 شهریور 1392, 01:33 صبح
لی من توی برنامم با استفاده از تابع میخوام کلاسم رو بسازم یعنی Create کردن داخل تابع اتفاق میوفته و حالا نمیدونم این کار درست هست یا نه
Create یک تابع هست که موقع ساخته شدن شی اجرا میشه که شما میتونید اون رو به دلخواه خودتون تعریف کنید.
در قسمت public به شکل constructor Create... با پارامتر های ورودیه دلخواه. این کار رو که خودتون انجام دادین! میدونید! نیازی به تابع دیگه نیست ولی میتونید مثل روش بنده یه تابع تعریف کنید.

کبار کلاس Test رو میسازه با حالتی که من نمیخوام اتفاق بیوفته.
شما تابع Create مخصوص خودتون رو تعریف کنید. اون طور که میخاید عمل کنه.

درصورتی که حالت درست ساخت شدن کلاس توی تابع اتفاق میوفته
ببریدش توی constructor Create خوده شی.

sara.mahdavi
چهارشنبه 13 شهریور 1392, 13:05 عصر
من بصورت عملی دقیق نمی فهمم شما چی می خواهی :چشمک:
یک بار دقیق تعریف کن چه انتظاری داری از برنامه، تا ببینیم چی می شه.

ببینید من توی پست 10 گفتم که دقیق میخوام چیکار کنه
میخوام همون کاری که توی مثال Test Class 2.rar (http://barnamenevis.org/attachment.php?attachmentid=110052&d=1378098585) هست رو انجام بده
توی این مثال، تابع خارج از کلاس تعریف شده و من میخوام اگه امکانش هست این مثال مثل یک کامپوننت یا یک کلاس کلی برای ایجاد آزمون عمل کنه
حالا با این مطالبی که گفتید و توی آزموش ها دیدم نمیدونم چطوری کار کنم چون هنوز این مطالب برام گنگه:ناراحت:
بازم ممنون:چشمک:

یوسف زالی
چهارشنبه 13 شهریور 1392, 14:47 عصر
خب در همون پست 11 نمونه کدتون رو گذاشتم.
برای همین متوجه نمی شم.

sara.mahdavi
چهارشنبه 13 شهریور 1392, 15:57 عصر
خب اونجا فقط یک کامه Class اضافه کردید که اون نمیدونم چ کاری انجام میده بعدشم من گفتم میخوام داخل کلاس از تابع استفاده کنم ولی شما کدی که نوشتید توی همون کلاس TForm هست و جاش تغییری نکرده :گیج:
خب اگه امکانش هست یکم بیشتر توضیح بدید فکر کنید من هیچی نمیدونم:افسرده: (که واقعا هم همینطور هس):ناراحت:

یوسف زالی
چهارشنبه 13 شهریور 1392, 16:59 عصر
همون یک کلمه کلی اثر داره! مثل گفتن بله یا نگفتنش سر سفره عقده! :دی

داستان رو دوباره تکرار می کنم، امیدوارم راهنمایی تون کرده باشه،

ما در حالت کلی سه نوع تابع (یا پروسیجر) داریم،
نوع اول: تابع معمولی که در فضای یونیت و خارج از کلاس تعریف می شه
نوع دوم: تابع آبجکت، که در دل یک کلاس بدون پیشوند خاصی تعریف می شه
نوع سوم: تابع استاتیک کلاس، که در فضای کلاس تعریف می شه با پیشوند Class

مثال ها:
----------
نوع اول:



procedure Proc1;

این کار می تونه بصورت تودرتو انجام بشه، یعنی می تونید در تابع یا پروسیجری از هر سه نوع، یک سری توابع یا پروسیجر های تودرتو هم داشته باشید.


نوع دوم:


TC = class
procedure Proc1;
end;


نوع سوم:


TC = class
class procedure Proc1;
end;


اشاره گر ها به این توابع و پروسیجر ها به این صورته:
Var
P1: procedure;
P2: procedure of object;
P3: procedure of object;

نکته:
اشاره گری داریم در هر کلاس به نام Self که:
در متد (= توابع درون کلاس) های عادی به خود شی اشاره می کنه
در متد های استاتیک به کلاس (!!) اشاره می کنه.

متدهای استاتیک برای کاربرد های زیر مناسبند:
1- سازنده ها و مخرب ها
2- کلاس هایی که برای جمع بندی یک مبحث (مثل Math یا Calendar) بکار می روند
3- متدهای متفرقه ای که لزومی به گرفتن حافظه ندارند

مثال:


TMath = class
public
class function PI: real;
class function E: real;
class function DistanceBetween(p1, p2: TPoint): real;
end;
.
.
{ TMath }

class function TMath.DistanceBetween(p1, p2: TPoint): real;
begin
Result := Hypot(p1.X -p2.X, p1.Y -p2.Y)
end;

class function TMath.E: real;
begin
Result := 2.71
end;

class function TMath.PI: real;
begin
result := 3.1415
end;

طریقه استفاده:


procedure TForm1.Button1Click(Sender: TObject);
var
r: real;
begin
r := TMath.PI;
end;


همون طور که دیدید بدون این که یک شی از TMath بسازیم داریم از توابع درونش استفاده می کنیم.

اگر دارید برای توابع ساخت یک شی چنین فکری می کنید، کامپایلر قبل از شما چنین فکری کرده، کافیه Create رو OverRide یا OverLoad کنید.

موفق باشید.

sara.mahdavi
چهارشنبه 13 شهریور 1392, 21:09 عصر
همون یک کلمه کلی اثر داره! مثل گفتن بله یا نگفتنش سر سفره عقده! :دی
:قهقهه::قهقهه::قهقهه:

ممنون از توضیحتون من توی این مثال هایی که میزنید متوجه میشم و میتونم مثل همین مثال ها کلاس و تابع بسازم
ولی وقتی میخوام توی برنامه خودم پیاده کنم به مشکل میخورم و همش به ارور برمیخورم و نمیدونم دارم درست عمل میکنم یا نه ؟ اصلا این تابعی که ساختم جای درستیه و...
:ناراحت:مثل اینکه چاره ای نیس مجبورم تابع رو هر جایی که این کلاس رو احتیاج داشتم بنویسم

ممنون از تمامی دوستان :قلب:

sara.mahdavi
پنج شنبه 14 شهریور 1392, 08:21 صبح
دو3تان خوبم بلاخره موفق شدم البته با راهنمایی های شما بخصوص آقا یوسف :چشمک:

فقط الان تنها مشکلی که دارم اینه که برای تعریف متغیرهای عمومی همین تابع وقتی که اون ها(متغییرها) رو داخل کلاسم در قسمت protected میذارم ارور میده ولی وقتی در قسمت تعریف عمومی یونیت میذارم همه چیز درسته

ممنون میشم این مورد رو هم راهنمایی کنید:قلب:

یوسف زالی
پنج شنبه 14 شهریور 1392, 12:27 عصر
خب دقت نکردی که بازم!
پست دو رو ببین:


طبیعیه که نباید از مقادیر حافظه ای شی مربوطه استفاده کنید چون هنوز شیئی ندارید.

وقتی پارامتری رو در قسمت Private می گذاری تا وقتی شی ساخته نشده پارامتر حافظه ای نداره که بشه ازش استفاده کرد. مثل اینه که بگید:


TButton.Tag := 1

خب این غلطه،
اگر نیاز به خروجی دارید می تونید از پارامترهای ارجاع استفاده کنید، ولی نمی تونید قبل از ایجاد یک شی، خصیصه هاش رو مقدار دهی کنید.
اگر منظورتون مقدار دهی اولیه یا همون Initialize کردن یک شی در مود های مختلفه، بهترین راه استفاده از Create های OverLoad شده هست.
موفق باشید.

sara.mahdavi
یک شنبه 17 شهریور 1392, 13:55 عصر
اگر منظورتون مقدار دهی اولیه یا همون Initialize کردن یک شی در مود های مختلفه، بهترین راه استفاده از Create های OverLoad شده هست.

منظورتون رو متوجه نمیشم یعنی برای تعریف متغییر ها یک Create بسازم که داخلش متغییرها رو تعریف کردم ؟؟؟

ببنید شما فرض کنید من یک متغییر به نام X دارم که توی قسمتهای مختلف کلاس ازش استفاده میکنم
من این متغییر رو الان در قسمت تعریف عمومی یونیت تعریف کردم و مشکلی نداره ولی در اصل این متغییر باید داخل خود کلاس تعریف بشه ولی وقتی این کار رو میکنم
ارور میده
Instance member 'X' inaccessible here
لطفا ساده توضیح بدید

خیلی از لطفتون ممنونم:قلب:

یوسف زالی
یک شنبه 17 شهریور 1392, 16:28 عصر
Class Var رو امتحان کنید..
در نسخ جدید اضافه شده.
به این صورت شما متغیری در فضای کلاس خواهید داشت.

sara.mahdavi
یک شنبه 17 شهریور 1392, 19:30 عصر
درست شد فقط برای متغییر هایی که از نوع Integer تعریف کردم خطا میده


Published field 'Q_Number' not a class or interface type

یوسف زالی
یک شنبه 17 شهریور 1392, 19:55 عصر
خب چرا گذاشتید تو Published ؟ مگر دارید کامپوننت می نویسید؟ بگذارید تو Public

sara.mahdavi
یک شنبه 17 شهریور 1392, 22:16 عصر
ممنون درست شد:تشویق:
توی Published نذاشته بودم، زیر تعریف کلاس نوشته بودم

اما الان درست شد :لبخند:
واقعا ازتون ممنونم:قلب:

یوسف زالی
یک شنبه 17 شهریور 1392, 22:44 عصر
وقتی چیزی نمی نویسید یعنی Published.
خوشحالم که بالاخره درست شد :دی