TAHA
09-22-2009, 11:06 AM
زبان برنامه نویسی D قسمت دوم
D برای چه کسانی مناسب نیست؟
۱. به طور واقع بینانه ، هیچکس قصد تبدیل میلیونها خط از C/++C به D ندارد و از آنجا که D کد منبع اصلاح نشده C/++C را کامپایل نمیکند ، برای این مورد مناسب نیست. (D به هرحال API های C را به خوبی پشتیبانی میکند).
۲. برنامه های خیلی کوچک : یک زبان اسکریپتی یا دارای مفسر مانند Perl , Dmdscript , Python احتمالاً مناسبتر است.
۳. به عنوان زبان برنامهنویسی برای شروع: برای مبتدیها Python یا java مناسبتر است . D برای برنامه نویسان متوسط تا پیشرفته یک زبان دوم عالی است .
۴. زبان به کاربرد کلمات صحیح وسواس دارد. D یک زبان عملی است و هر خصیصه از آن ترجیحاً قابل مقایسه و ارزیابی در همان حداست تا در حد ایدهآل . به طور مثال D ساختارها و مفاهیمی دارد که به طور مجازی نیاز به اشارهگرها را برای امور پیش پا افتاده ازبین میبرد. به طور مشابه تغییر نوعها هنوز وجود دارد برای آن جایی که سیستم نوع ، نیاز به نادیده گرفتن دارد.
خصوصیات اصلی
D
این قسمت برخی خصوصیات جالبتر D(نسبت به C) را در دستههای مختلف طبقهبندی میکند.
برنامهنویسی شییءگرا
کلاسها : طبیعت شییء گرای D از کلاسها آغاز میشود. مدل وراثت ، وراثت یگانه است که با روابط تقویت میشود. شییء کلاس در ریشهی درخت وراثت می نشیند. بنابراین تمام کلاسها یک مجموعه متداول تابعی را اجرا میکنند. کلاسها به وسیله ارجاع معرفی میشوند و چنان کد پیچیدهای برای آنکه پساز استثناها پاک شود نیاز نیست.
تعریف مجدد عملگرها: میتوان کلاس را برآن واداشت که با استفاده از عملگرهای موجود ، سیستم نوع را برای پشتیبانی نوعهای جدید گسترش دهد. مثلاً ایجاد کلاس اعداد بزرگ و سپس تعریف مجدد عملگرهای (/,*,_,+) برای توانایی استفاده از آن ها در املای عبارات جبری معمولی.
فراوری( Productivity)
پیمانهها : فایلهای منبع دارای ارتباطی یک به یک با پیمانهها هستند. به جای include# نمودن یک فایل از اعلان ها ، فقط پیمانه را import مینماییم. هیچ نگرانی در مورد importهای متعدد از همان پیمانه نیست همچنین نیازی به پوشاندن فایلهای header با ifndef# یا endif# یا pragma once# و از این قبیل نیست.
اعلان در برابر تعریف
++C معمولاً نیاز دارد که توابع و کلاسها دوبار اعلان شوند یک اعلان که در فایلهای header صورت میگیرد و تعریف که در فایل منبع با پسوند “C.” . این یک روند مستعد خطا و کسل کننده است . به طور واضح برنامهنویس فقط نیاز دارد که یک بار آن را بنویسد و سپس کامپایلر باید دادههای اعلان را بسط دهد و برای وارد کردن نمادین در دسترس قرار دهد. دقیقاً آن گونه که D میکند:
مثال:
class ABC
{
int func() { return 7; }
static int z = 7;
}
int q;
دیگر نیاز به تعریف جدای توابع عضو، اعضای استاتیک ، extern ها یا املاهایی مانند زیر نیست:
int ABC::func() { return 7; }
int ABC::z = 7;
extern int q;
تذکر : البته در ++C توابع جزیی مانند {;return 7} به صورت inline هم نوشته میشوند اما توابع پیچیده نه. علاوه برآن اگر یک ارجاع بعد از آن موجود باشد تابع نیاز به الگو دارد که از قبل موجود باشد مثال زیر در ++C کار نمی کند.
class Foo
{
int foo(Bar *c) { return c->bar; }
};
class Bar
{
public: int bar() { return 3; }
};
اما کد همارز در D کار می کند:
class Foo
{
int foo(Bar c) { return c.bar; }
}
class Bar
{
int bar() { return 3; }
}
اینکه یک تابع D به صورت inline است یا نه توسط تنظیمات بهینهساز قابل کنترل است .
قالبها
قالبهای D روشی واضح برای پشتیبانی برنامهسازی عمومی همراه با قدرت اختصاصیسازی به صورت قسمت به قسمت ، پیشنهاد میکند.
آرایههای شرکتپذیر
آرایههای شرکتپذیر آرایههایی هستند با یک نوع داده قراردادی (اختیاری) به عنوان ایندکس به جای آنکه به یک ایندکس از نوع اعداد صحیح محدود باشند. در اصل آرایههای شرکتپذیر جدولهای در هم سازی(hash ) هستند. این آرایهها ساختن سریع ، کارا و خالی از اشکال جدولهای سمبل را آسان مینماید.
تعریف نوعهای واقعی
تعریف نوعهای C و ++C در حقیقت نام مستعار نوع هستند طوریکه هیچ نوع جدیدی به طور واقعی مطرح نمیشود. D ، تعریف نوعهای واقعی پیادهسازی میکند جایی که:
typedef int handle;
به طور واقعی یک نوع جدید به نام handle ایجاد میکند . بر کنترل نوع تأکید شده است و تعریف نوعها در تعریف مجدد توابع شریک میشوند. برای مثال :
int foo(int i);
int foo(handle h);
نوع bit
نوع داده پایه بیت است و D یک نوع داده با نام bit دارد . این امر بیش از همه در ساخت آرایههایی از بیتها مفید است:
bit [ ] foo;
توابع
D توقع پشتیبانی از توابع معمول از جمله توابع عمومی ، توابع مجدد تعریف شده ، توابع inline ، توابع عضو ، توابع مجازی ، اشارهگرها به توابع و … را داشته است علاوه برآن :
توابع تودرتو
توابع میتوانند درون توابع دیگر قرار گیرند. این امر در ساخت کد ، خاصیت locality و تکنیکهای بستهبندی توابع بسیار مفید است.
لفظهای توابع Functionliterals
توابع بینام میتوانند به طور مستقیم در یک عبارت جای داده شوند.
وکالت(Closure) دینامیک
توابع محصور شده و توابع عضو کلاس بوسیله وکالت (delegate) میتوانند ارجاع داده شوند که این باعث آسان تر شدن و type safe شدن برنامهسازی عمومی میشود.
پارامترهای ورودی، خروجی ، ورودی-خروجی
این خصوصیسازی نه تنها کمک میکند که توابع خود مستندتر شوند بلکه بسیاری از موارد لزوم اشارهگرها را بدون قربانی کردن هیچ چیز حذف و امکاناتی را برای کمک بیشتربه کامپایلر در پیدا کردن اشکالات کد فراهم میکند.
بدین ترتیب برای D این امکان فراهم میشود که مستقیماً با یک بازه وسیعتری از APIهای بیگانه ارتباط برقرار کند. و هیچ نیازی برای کارهای جانبی مانند زبانهای تعریف ارتباطات وجود ندارد.
آرایهها
آرایههای C اشتباهات متعددی دارند که میتوانند تصحیح شوند:
۱. اطلاعات بعد با آرایه همراه نیست و بنابراین باید ذخیرهشده و جداگانه ارسال شود . مثال کلاسیک این مورد پارامترهای argc و argv هستند که به main فرستاده میشوند.
main (int argc , char*argv[])
۲. آرایهها اشیاء سطح اول نیستند. وقتی یک آرایه به عنوان پارامتر به یک تابع فرستاده میشود به یک اشارهگر برگردانده میشود . حتی با اینکه الگوی تابع به طور گیج کنندهای می گوید که این آرایه است. وقتی این برگرداندن انجام میشود تمام اطلاعات نوع آرایه گم میشود.
۳.آرایههای C قابل تغییر اندازه نیستند . این بدان معنی است که حتی چیزهای ساده ،انبوه و متراکم میگردد. مانند یک پشته که نیازدارد به عنوان یک کلاس پیچیده ساخته شود.
۴.مرز یک آرایه C قابل کنترل نیست چون اصلاً مرز آرایه مشخص نیست.
۵.آرایهها در C با علامت [ ] پس از شناسه اعلان میشوند . این به یک املای بیخود و گیج کننده در اعلان اشیایی مانند اشارهگر به یک آرایه میانجامد :
int (*array ) [3];
در D علامت [ ] در سمت چپ قرار میگیرد که فهم آن بسیار سادهتر است.
int [3] * array; // اعلان یک اشارهگر به یک آرایه سهتایی از اعداد صحیح
Long [ ] func (int x); //تابعی که آرایه ای از اعداد صحیح بلند را برمی گرداند
آرایههای D در چهار نوع میآیند : اشارهگرها ، آرایههای استاتیک ، آرایههای دینامیک و آرایههای شرکتپذیر ،قسمت آرایهها را ببنید !
رشتهها
پردازش رشتهها آن قدر متداول است (و آن قدر در C و ++C زمخت و بدترکیب) که نیازمند پشتیبانی مستقیم در زبان برنامه سازی است. زبانهای مدرن از جمله D ، الحاق رشتهها ، کپی کردن و … را در دست میگیرند . رشتهها رهاورد مستقیم پردازش بهینه شده آرایهها هستند.
D برای چه کسانی مناسب نیست؟
۱. به طور واقع بینانه ، هیچکس قصد تبدیل میلیونها خط از C/++C به D ندارد و از آنجا که D کد منبع اصلاح نشده C/++C را کامپایل نمیکند ، برای این مورد مناسب نیست. (D به هرحال API های C را به خوبی پشتیبانی میکند).
۲. برنامه های خیلی کوچک : یک زبان اسکریپتی یا دارای مفسر مانند Perl , Dmdscript , Python احتمالاً مناسبتر است.
۳. به عنوان زبان برنامهنویسی برای شروع: برای مبتدیها Python یا java مناسبتر است . D برای برنامه نویسان متوسط تا پیشرفته یک زبان دوم عالی است .
۴. زبان به کاربرد کلمات صحیح وسواس دارد. D یک زبان عملی است و هر خصیصه از آن ترجیحاً قابل مقایسه و ارزیابی در همان حداست تا در حد ایدهآل . به طور مثال D ساختارها و مفاهیمی دارد که به طور مجازی نیاز به اشارهگرها را برای امور پیش پا افتاده ازبین میبرد. به طور مشابه تغییر نوعها هنوز وجود دارد برای آن جایی که سیستم نوع ، نیاز به نادیده گرفتن دارد.
خصوصیات اصلی
D
این قسمت برخی خصوصیات جالبتر D(نسبت به C) را در دستههای مختلف طبقهبندی میکند.
برنامهنویسی شییءگرا
کلاسها : طبیعت شییء گرای D از کلاسها آغاز میشود. مدل وراثت ، وراثت یگانه است که با روابط تقویت میشود. شییء کلاس در ریشهی درخت وراثت می نشیند. بنابراین تمام کلاسها یک مجموعه متداول تابعی را اجرا میکنند. کلاسها به وسیله ارجاع معرفی میشوند و چنان کد پیچیدهای برای آنکه پساز استثناها پاک شود نیاز نیست.
تعریف مجدد عملگرها: میتوان کلاس را برآن واداشت که با استفاده از عملگرهای موجود ، سیستم نوع را برای پشتیبانی نوعهای جدید گسترش دهد. مثلاً ایجاد کلاس اعداد بزرگ و سپس تعریف مجدد عملگرهای (/,*,_,+) برای توانایی استفاده از آن ها در املای عبارات جبری معمولی.
فراوری( Productivity)
پیمانهها : فایلهای منبع دارای ارتباطی یک به یک با پیمانهها هستند. به جای include# نمودن یک فایل از اعلان ها ، فقط پیمانه را import مینماییم. هیچ نگرانی در مورد importهای متعدد از همان پیمانه نیست همچنین نیازی به پوشاندن فایلهای header با ifndef# یا endif# یا pragma once# و از این قبیل نیست.
اعلان در برابر تعریف
++C معمولاً نیاز دارد که توابع و کلاسها دوبار اعلان شوند یک اعلان که در فایلهای header صورت میگیرد و تعریف که در فایل منبع با پسوند “C.” . این یک روند مستعد خطا و کسل کننده است . به طور واضح برنامهنویس فقط نیاز دارد که یک بار آن را بنویسد و سپس کامپایلر باید دادههای اعلان را بسط دهد و برای وارد کردن نمادین در دسترس قرار دهد. دقیقاً آن گونه که D میکند:
مثال:
class ABC
{
int func() { return 7; }
static int z = 7;
}
int q;
دیگر نیاز به تعریف جدای توابع عضو، اعضای استاتیک ، extern ها یا املاهایی مانند زیر نیست:
int ABC::func() { return 7; }
int ABC::z = 7;
extern int q;
تذکر : البته در ++C توابع جزیی مانند {;return 7} به صورت inline هم نوشته میشوند اما توابع پیچیده نه. علاوه برآن اگر یک ارجاع بعد از آن موجود باشد تابع نیاز به الگو دارد که از قبل موجود باشد مثال زیر در ++C کار نمی کند.
class Foo
{
int foo(Bar *c) { return c->bar; }
};
class Bar
{
public: int bar() { return 3; }
};
اما کد همارز در D کار می کند:
class Foo
{
int foo(Bar c) { return c.bar; }
}
class Bar
{
int bar() { return 3; }
}
اینکه یک تابع D به صورت inline است یا نه توسط تنظیمات بهینهساز قابل کنترل است .
قالبها
قالبهای D روشی واضح برای پشتیبانی برنامهسازی عمومی همراه با قدرت اختصاصیسازی به صورت قسمت به قسمت ، پیشنهاد میکند.
آرایههای شرکتپذیر
آرایههای شرکتپذیر آرایههایی هستند با یک نوع داده قراردادی (اختیاری) به عنوان ایندکس به جای آنکه به یک ایندکس از نوع اعداد صحیح محدود باشند. در اصل آرایههای شرکتپذیر جدولهای در هم سازی(hash ) هستند. این آرایهها ساختن سریع ، کارا و خالی از اشکال جدولهای سمبل را آسان مینماید.
تعریف نوعهای واقعی
تعریف نوعهای C و ++C در حقیقت نام مستعار نوع هستند طوریکه هیچ نوع جدیدی به طور واقعی مطرح نمیشود. D ، تعریف نوعهای واقعی پیادهسازی میکند جایی که:
typedef int handle;
به طور واقعی یک نوع جدید به نام handle ایجاد میکند . بر کنترل نوع تأکید شده است و تعریف نوعها در تعریف مجدد توابع شریک میشوند. برای مثال :
int foo(int i);
int foo(handle h);
نوع bit
نوع داده پایه بیت است و D یک نوع داده با نام bit دارد . این امر بیش از همه در ساخت آرایههایی از بیتها مفید است:
bit [ ] foo;
توابع
D توقع پشتیبانی از توابع معمول از جمله توابع عمومی ، توابع مجدد تعریف شده ، توابع inline ، توابع عضو ، توابع مجازی ، اشارهگرها به توابع و … را داشته است علاوه برآن :
توابع تودرتو
توابع میتوانند درون توابع دیگر قرار گیرند. این امر در ساخت کد ، خاصیت locality و تکنیکهای بستهبندی توابع بسیار مفید است.
لفظهای توابع Functionliterals
توابع بینام میتوانند به طور مستقیم در یک عبارت جای داده شوند.
وکالت(Closure) دینامیک
توابع محصور شده و توابع عضو کلاس بوسیله وکالت (delegate) میتوانند ارجاع داده شوند که این باعث آسان تر شدن و type safe شدن برنامهسازی عمومی میشود.
پارامترهای ورودی، خروجی ، ورودی-خروجی
این خصوصیسازی نه تنها کمک میکند که توابع خود مستندتر شوند بلکه بسیاری از موارد لزوم اشارهگرها را بدون قربانی کردن هیچ چیز حذف و امکاناتی را برای کمک بیشتربه کامپایلر در پیدا کردن اشکالات کد فراهم میکند.
بدین ترتیب برای D این امکان فراهم میشود که مستقیماً با یک بازه وسیعتری از APIهای بیگانه ارتباط برقرار کند. و هیچ نیازی برای کارهای جانبی مانند زبانهای تعریف ارتباطات وجود ندارد.
آرایهها
آرایههای C اشتباهات متعددی دارند که میتوانند تصحیح شوند:
۱. اطلاعات بعد با آرایه همراه نیست و بنابراین باید ذخیرهشده و جداگانه ارسال شود . مثال کلاسیک این مورد پارامترهای argc و argv هستند که به main فرستاده میشوند.
main (int argc , char*argv[])
۲. آرایهها اشیاء سطح اول نیستند. وقتی یک آرایه به عنوان پارامتر به یک تابع فرستاده میشود به یک اشارهگر برگردانده میشود . حتی با اینکه الگوی تابع به طور گیج کنندهای می گوید که این آرایه است. وقتی این برگرداندن انجام میشود تمام اطلاعات نوع آرایه گم میشود.
۳.آرایههای C قابل تغییر اندازه نیستند . این بدان معنی است که حتی چیزهای ساده ،انبوه و متراکم میگردد. مانند یک پشته که نیازدارد به عنوان یک کلاس پیچیده ساخته شود.
۴.مرز یک آرایه C قابل کنترل نیست چون اصلاً مرز آرایه مشخص نیست.
۵.آرایهها در C با علامت [ ] پس از شناسه اعلان میشوند . این به یک املای بیخود و گیج کننده در اعلان اشیایی مانند اشارهگر به یک آرایه میانجامد :
int (*array ) [3];
در D علامت [ ] در سمت چپ قرار میگیرد که فهم آن بسیار سادهتر است.
int [3] * array; // اعلان یک اشارهگر به یک آرایه سهتایی از اعداد صحیح
Long [ ] func (int x); //تابعی که آرایه ای از اعداد صحیح بلند را برمی گرداند
آرایههای D در چهار نوع میآیند : اشارهگرها ، آرایههای استاتیک ، آرایههای دینامیک و آرایههای شرکتپذیر ،قسمت آرایهها را ببنید !
رشتهها
پردازش رشتهها آن قدر متداول است (و آن قدر در C و ++C زمخت و بدترکیب) که نیازمند پشتیبانی مستقیم در زبان برنامه سازی است. زبانهای مدرن از جمله D ، الحاق رشتهها ، کپی کردن و … را در دست میگیرند . رشتهها رهاورد مستقیم پردازش بهینه شده آرایهها هستند.