PDA

View Full Version : مبتدی: مشکل در یک برنامه کوچک



phpphp7
سه شنبه 25 فروردین 1394, 19:07 عصر
سلام دوستان !
ابتدا کد ها رو مشاهده بفرمایید :




<?php

class MyClass
{
public $prop1 = "I'm a class property!";

public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}

public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}

public function __toString()
{
echo "Using the toString method: ";
return $this->getProperty();
}

public function setProperty($newval)
{
$this->prop1 = $newval;
}

public function getProperty()
{
return $this->prop1 . "<br />";
}
}

class MyOtherClass extends MyClass
{
public function newMethod()
{
echo "From a new method in " . __CLASS__ . ".<br />";
}
}

// Create a new object
$newobj = new MyOtherClass;

// Output the object as a string
echo $newobj->newMethod();

// Use a method from the parent class
echo $newobj->getProperty();

?>




طبق 3 خط آخر برنامه ، خروجی باید به صورت زیر باشه :

From a new method in MyOtherClass.

I'm a class property!

پس چرا خروجی به صورت زیر هست ؟؟



The class "MyClass" was initiated!
From a new method in MyOtherClass.
I'm a class property!
The class "MyClass" was destroyed.

-سیّد-
سه شنبه 25 فروردین 1394, 19:56 عصر
اون پیغام‌ها در constructor و destructor کلاس چاپ می‌شن:




public function __construct()
{
echo 'The class "', __CLASS__, '" was initiated!<br />';
}


و




public function __destruct()
{
echo 'The class "', __CLASS__, '" was destroyed.<br />';
}



اگه با مفاهیم شیءگرایی آشنایی ندارید، به صورت خیلی کوتاه عرض کنم که وقتی یک شیء ساخته می‌شه (new)، اولین اتفاقی که می‌افته اینه که constructor اش فراخوانی می‌شه. توی زبان PHP، تابع constructor رو به صورت یک تابع با اسم خاص construct__ معرفی می‌کنیم. یعنی انگار کد new شما که به صورت

$newobj = new MyOtherClass;
بود، به این شکل ترجمه می‌شه:

$newobj = MyOtherClass->__construct();
پس new کردن از یه کلاس، انگار یعنی تابع construct__ رو صدا زدید. برای همین اون خط اول چاپ می‌شه.

بعد هم در نهایت وقتی یه شیء (object) رو از بین می‌برید، تابع desctructor اش فراخوانی می‌شه که توی PHP به صورت destruct__ معرفی می‌شه. حالا کی یه شیء از بین می‌ره؟ یا توسط دستور unset، یا اگه این کارو نکنید (که اینجا نکردید)، خود php در انتهای کار اسکریپت، شیءهای سرگردان(!) رو از بین می‌بره. برای همین در انتهای اسکریپت شما این شیء از بین می‌ره و در نتیجه desctructor اش صدا زده می‌شه که اون خط آخر رو چاپ می‌کنه.

phpphp7
سه شنبه 25 فروردین 1394, 21:37 عصر
اون پیغام‌ها در constructor و destructor کلاس چاپ می‌شن:

و


اگه با مفاهیم شیءگرایی آشنایی ندارید، به صورت خیلی کوتاه عرض کنم که وقتی یک شیء ساخته می‌شه (new)، اولین اتفاقی که می‌افته اینه که constructor اش فراخوانی می‌شه. توی زبان PHP، تابع constructor رو به صورت یک تابع با اسم خاص construct__ معرفی می‌کنیم. یعنی انگار کد new شما که به صورت

$newobj = new MyOtherClass;
بود، به این شکل ترجمه می‌شه:

$newobj = MyOtherClass->__construct();
پس new کردن از یه کلاس، انگار یعنی تابع construct__ رو صدا زدید. برای همین اون خط اول چاپ می‌شه.

بعد هم در نهایت وقتی یه شیء (object) رو از بین می‌برید، تابع desctructor اش فراخوانی می‌شه که توی PHP به صورت destruct__ معرفی می‌شه. حالا کی یه شیء از بین می‌ره؟ یا توسط دستور unset، یا اگه این کارو نکنید (که اینجا نکردید)، خود php در انتهای کار اسکریپت، شیءهای سرگردان(!) رو از بین می‌بره. برای همین در انتهای اسکریپت شما این شیء از بین می‌ره و در نتیجه desctructor اش صدا زده می‌شه که اون خط آخر رو چاپ می‌کنه.
سلام
خیلی ممنون آقا سید بابت توضیحات کامل
یعنی هنگامی که یک شی ساخت میشه ، اگه داخل کلاس فوق __construct و destruct__ باشه ، در هنگام لود صفحه ، در اولین خط __construct و در آخرین خط destruct__ رو چاپ میکنه؟

آیا درست متوجه شده ام ؟

این "از بین بردن کلاس" رو متوجه نشدم.

-سیّد-
سه شنبه 25 فروردین 1394, 22:22 عصر
سلام
خیلی ممنون آقا سید بابت توضیحات کامل
یعنی هنگامی که یک شی ساخت میشه ، اگه داخل کلاس فوق __construct و destruct__ باشه ، در هنگام لود صفحه ، در اولین خط __construct و در آخرین خط destruct__ رو چاپ میکنه؟

آیا درست متوجه شده ام ؟

و علیکم السلام
نه، اینطوری نیست!
ببینید شما دارید دو تا مفهوم رو با هم قاطی می‌کنید: مفهوم شیءگرایی و مفهوم زبان‌های تحت وب.

اول، مفهوم شیءگرایی: این مفاهیم توی زبان‌هایی به وجود اومدن و گسترش پیدا کردن که هیچ ارتباطی به وب نداشتن. مثلاً زبان جاوا کلاً بر مبنای شیءگرایی بنا شده. اما PHP، کلاً از ابتدا مفهوم شیءگرایی رو توی خودش نداشت و در نسخه‌ی ۴ به اون اضافه کردن (اگه درست یادم باشه).
بنابراین constructor و destructor ارتباطی به لود شدن صفحه ندارن. اگه بتونید این دو تا رو کاملاً از هم جدا کنید خیلی بهتون توی گرفتن مطلب کمک می‌کنه.

دوم، مفهوم زبان‌های تحت وب: توی یک زبان تحت وب مانند PHP، برنامه‌ی شما اصولاً با فرستاده شدن یک درخواست از سمت کاربر به سرور اجرا می‌شه (هر چند که می‌شه جداگانه هم اجراش کرد، ولی روش اصلی اینه و در واقع برای این طراحی شده (اصلاً برای همین بهش می‌گن زبان تحت وب!)). بنابراین هنگام لود شدن صفحه، برنامه‌ی شما از اول تا آخرش اجرا می‌شه. پس constructor و destructor هیچ ارتباطی به لود شدن صفحه و این که خط اول و خط آخر بخوان چاپ بشن نداره.

پس چی شد؟
اول کد رو (بدون در نظر گرفتن این که روی وب داره اجرا می‌شه و صفحه‌ای لود می‌شه) بررسی می‌کنیم. می‌بینیم که یه کلاس توش تعریف شده که شامل constructor و destructor هست. خوب تا اینجا هنوز هیچ اتفاقی نیافتاده و هیچی چاپ نشده (فقط یه کلاس تعریف شده، یعنی فرض کنید یه ماشین می‌خواین بسازین، در واقع شما اینجا فقط یه طراحی از ماشینی که می‌خواین بسازین رو به سیستم دادید و هنوز ماشینی تولید نشده).
حالا بعدش میایم و یک نمونه از اون کلاس رو می‌سازیم (توسط new). اینجا داریم یه دونه از اون ماشینا می‌سازیم. در واقع اینجا خط تولید رو راه انداختیم.
خوب به محض این که یه شیء رو می‌سازید، تابع construct__ اون صدا زده می‌شه. و چون توی این کد قبلش چیزی چاپ نکردید، اولین خطی که چاپ می‌شه چیزی هست که توی constructor هست. برای این که بهتر بتونید کد رو trace کنید، این خط رو قبل از new کردن اضافه کنید:

echo 'Before new';
اصلاً بد نیست بین هر دو تا خط اون انتها یه دونه echo اضافه کنید:


echo '111';

// Create a new object
$newobj = new MyOtherClass;

echo '222';

// Output the object as a string
echo $newobj->newMethod();

echo '333';

// Use a method from the parent class
echo $newobj->getProperty();

echo '444';

با اجرای این کد قشنگ می‌بینید که اول ۱۱۱ چاپ می‌شه، بعد پیغام constructor (چون new کردید)، بعد ۲۲۲، و ...
در نهایت هم ۴۴۴ چاپ می‌شه، و بعد پیغام destructor.



این "از بین بردن کلاس" رو متوجه نشدم.
کلاس رو که از بین نمی‌برید! شیء ساخته شده رو از بین می‌برید.
وقتی که کار اسکریپت شما تموم می‌شه، سیستم می‌خواد بای بای کنه و بره پی کارش. خوب برای این کار می‌خواد حافظه رو رها کنه که سیستم بتونه از اون حافظه استفاده کنه. برای همین هر شیء که توی حافظه هست رو نابود می‌کنه (destruct). هنگام نابود شدن یه شیء، تابع destruct__ اون صدا زده می‌شه.

حالا شما می‌تونید خودتون یه مقدار حافظه رو مدیریت کنید و به محض این که دیدید دیگه نمی‌خواین از یه شیء استفاده کنین، اون رو دستی نابود کنین (به جای این که بذارین سیستم خودش اون رو به صورت اتوماتیک نابود کنه). این کار توسط دستور unset انجام می‌شه:

unset($newobj);
برای اطمینان، یه echo هم بعد از unset بذارید که ببینید به محض صدا زدن این دستور، تابع destruct__ اجرا می‌شه.