به همراه مفهوم نوع, یکی از مفاهیم باارزشی که به وسیلهی زبان پاسکال معرفی گردید, توانایی تعریف نوعهای دادهای جدید در یک برنامه بود. برنامهنویسان میتوانند با استفاده از سازندههای نوع, مانند نوع های زیردامنه (subrange types), نوعهای آرایهای, نوعهای رکوردی, نوع های برشماری (enumerated), نوعهای اشارهگر, و نوعهای مجموعه, نوعهای جدیدی تعریف کنند. مهمترین نوع دادهای تعریف شده توسط کاربر کلاس است, که بخشی از گسترش شیءگرای آبجکت پاسکال است که در این کتاب مورد بحث قرار نگرفته است.
شاید بگویید که سازندههای نوع در بسیاری از دیگر زبانهای برنامهنویسی هم وجود دارند, و این البته درست است, ولی پاسکال اولین زبانی بود که این مفهوم را به صورت رسمی و بسیار دقیق ارائه کرد. هنوز هم کمتر زبانی میشناسیم که چنین ساز و کارهای زیادی برای تعریف نوعهای جدید داشته باشد.
نوعهای بانام و بینام
به هر نوع ممکن است نامی داده شود که بعداً بتوان از آن استفاده کرد, و یا ممکن است نوع مستقیماً بر وی متغیر اعمال شود. برای دادن نام به نوع باید بخش خاصی در برنامه ایجاد کنید, مانند مثال زیر:
type
// subrange definition
Uppercase = 'A'..'Z';
// array definition
Temperatures = array [1..24] of Integer;
// record definition
Date = record
Month: Byte;
Day: Byte;
Year: Integer;
end;
// enumerated type definition
Colors = (Red, Yellow, Green, Cyan, Blue, Violet);
// set definition
Letters = set of Char;
برای تعریف متغیر از یک نوع جدید بدون اینکه نام صریحی به نوع داده شود, میتوان از سازههای مشابهی استفاده کرد. برای مثال:
var
DecemberTemperature: array [1..31] of Byte;
ColorCode: array [Red..Violet] of Word;
Palette: set of Colors;
توجه: به طور کلی, باید از کاربرد نوعهای بینام مانند نمونهی بالا اجتناب کنید, زیرا نمیتوانید آنها را به عنوان پارامتر به یک روال بدهید, و یا متغیرهای دیگری از همان نوع تعریف کنید. در واقع, قواعد سازگاری نوع در پاسکال مبتنی بر نام نوعها است, نه تعریف واقعی آنها. دو متغیر که نوع یکسان دارند, با هم سازگار نیستند, مگر آنکه نوعهای آنها دقیقاً نام یکسانی داشته باشد. برای نوعهای بینام هم توسط تدوینگر یک نام درونی در نظر گرفته میشود. هرگاه به متغیری با یک ساختمان پیچیده نیاز دارید, نوع جدیدی برای آن تعریف کنید, و مطمئن باشید که از وقتی که صرف آن کردهاید, پشیمان نخواهد شد.
اما معنای این نوعهای تعریف شده چیست؟ برای افرادی که با سازههای نوع پاسکال آشنا نیستند, توضیحاتی ارائه میکنیم. در ضمن, تفاوتهای این سازهها را با سایر زبانهای برنامهنویسی مورد اشاره قرار خواهیم داد, بنا بر این، اگر هم با تعاریف نوع بالا از قبل آشنایی دارید, بد نیست که قسمتهای زیر را بخوانید. در نهایت چند مثال دلفی را نشان خواهیم داد و ابزارهایی را معرفی خواهیم کرد که امکان دستیابی به اطلاعات نوع را به صورت پویا فراهم میکنند.
نوعهای زیردامنه
نوع زیردامنه, دامنهای از مقادیر را در درون دامنهی یک نوع دیگر تعریف میکند (و از این رو به آن زیردامنه میگویند). مثلاً میتوانید زیردامنهای از نوع Integer از 1 تا 10 و یا از 100 تا 1000 تعریف کنید, و یا میتوانید زیردامنهای از نوع Char تعریف نمایید. برای مثال:
type
Ten = 1..10;
OverHundred = 100..1000;
Uppercase = 'A'..'Z';
در تعریف یک زیردامنه, لازم نیست که نام نوع مبنا را ذکر کنید. تنها چیزی که لازم است این است که دو مقدار ثابت از آن نوع ارائه کنید. نوع اصلی باید یک نوع ترتیبی باشد, و نوع حاصل هم یک نوع ترتیبی خواهد بود.
وقتی یک زیردامنه تعریف کردید, به طور قانونی میتوانید مقادیری از همان دامنه به آن اختصاص دهید. مثلاً برنامهی زیر درست است:
var
UppLetter: UpperCase;
begin
UppLetter := 'F';
ولی این یکی درست نیست:
var
UppLetter: UpperCase;
begin
UppLetter := 'e'; // compile-time error
کد اخیر باعث بروز خطای زمان تدوین (compile-time error) با مضمون زیر میشود : "عبارت ثابت کرانهای زیردامنه را نقض میکند." ("Constant expression violates subrange bounds.") در عوض, اگر کد زیر را بنویسید:
var
UppLetter: Uppercase;
Letter: Char;
begin
Letter :='e';
UppLetter := Letter;
دلفی آن را تدوین خواهد کرد. در زمان اجرا اگر گزینهی تدوینگر وارسی دامنه (Range Checking compiler option) را (که در صفحهی تدوینگر از پنجرهی گفتگوی گزینههای پروژه [Project Options] قرار دارد) فعال کرده باشید, یک پیغام خطای وارسی دامنه (range check error) دریافت خواهید کرد.
توجه: توصیه میکنم زمانی که مشغول تولید برنامه هستند, این گزینهی تدوینگر را فعال کنید تا خطازدایی (debug) قویتر و آسانتر باشد, زیرا در صورت بروز خطا به جای رفتارهای نامشخص, پیغام مشخصی ارائه خواهد شد. نهایتاً برای ساخت (build) نهایی برنامه میتوانید این گزینه را غیرفعال کنید تا برنامه کمی سریعتر شود. البته, اختلاف در واقع آن قدر کم است که من پیشنهاد میکنم که حتی در ساخت نهایی برنامه هم تمام این وارسیهای زمان اجرا را فعال کنید. در مورد سایر گزینههای وارسی زمان اجرا هم, مانند وارسی لبریزی و پشته (overflow and stack checking), بهتر است به همین پیشنهاد عمل کنید.
نوع های برشماری
نوعهای برشماری یکی دیگر از انواع دادهای تعریف شده توسط کاربر را تشکیل میدهند. در برشماری به جای تعیین زیردامنهای از یک نوع موجود, تمام مقادیر ممکن نوع مورد نظر را برمیشمارید