باکسینگ کیست؟ توضیح بده.
در علوم رایانه، «باکسینگ» یا «بسته‌بندی» (که با عنوان "wrapping" نیز شناخته می‌شود)، به فرایند قرار دادن یک نوع داده‌ی ابتدایی (primitive type) درون یک شیء اطلاق می‌شود؛ به‌گونه‌ای که بتوان از آن مقدار به‌عنوان یک مرجع (reference) استفاده کرد. «آن‌باکسینگ» یا «بازگشایی» (unboxing) به فرایند معکوس این عملیات اشاره دارد، یعنی استخراج مقدار اولیه از شیء بسته‌بندی‌شده. همچنین، اصطلاح «اتوباکسینگ» یا «بازگشایی خودکار» (autoboxing) به اعمال خودکار عملیات باکسینگ و/یا آن‌باکسینگ در زمان نیاز گفته می‌شود.بسته‌بندی.کاربرد برجستهٔ بسته‌بندی در زبان جاوا دیده می‌شود؛ جایی که به‌دلایلی مانند بهینه‌سازی عملکرد در زمان اجرا و تفاوت‌های نحوی و معنایی، میان نوع‌های ارجاعی (reference types) و مقداری (value types) تمایز وجود دارد. در جاوا، یک ساختار داده مانند codice_1 تنها می‌تواند مقادیری از نوع codice_2 را در خود ذخیره کند. اگرچه ممکن است بخواهیم یک codice_1 از نوع codice_4 داشته باشیم، این کار به‌صورت مستقیم امکان‌پذیر نیست. در عوض، جاوا برای هر نوع دادهٔ ابتدایی (primitive type)، یک کلاس بسته‌بندی (primitive wrapper class) متناظر تعریف کرده‌است، مانند:بدین ترتیب، می‌توان یک codice_1 با استفاده از نوع بسته‌بندی‌شدهٔ codice_5 تعریف کرد و مقادیر codice_4 را از طریق باکسینگ، به‌صورت شیءهای codice_5 در آن قرار داد. (با معرفی نوع‌های عمومی پارامتری (generic parameterized types) در نسخهٔ J2SE 5.0، این ساختار به‌صورت codice_15 تعریف می‌شود.)از سوی دیگر، زبان #C کلاس‌های بسته‌بندیِ نوع‌های ابتدایی ("primitive wrapper classes") را ندارد، اما امکان باکس‌کردن هر نوع مقداری (value type) را فراهم می‌کند؛ به‌طوری‌که نتیجه به‌صورت یک مرجع از نوع کلی codice_2 بازگردانده می‌شود.در زبان Objective-C نیز می‌توان هر مقدار ابتدایی را با قراردادن نماد codice_17 در ابتدای آن به یک شیء از نوع codice_18 تبدیل کرد (برای مثال: codice_19 یا codice_20). این قابلیت امکان افزودن چنین مقادیری را به مجموعه‌های استانداردی مانند codice_21 فراهم می‌سازد.در زبان Haskell، تقریباً هیچ مفهومی تحت عنوان «نوع ارجاعی» (reference type) وجود ندارد؛ با این حال، از اصطلاح «باکس‌شده» (boxed) برای اشاره به نمایش یکنواختِ «اشاره‌گر به ساختار union دارای برچسب» در زمان اجرا استفاده می‌شود.شیء باکس‌شده همواره نسخه‌ای کپی از مقدار اولیه است و معمولاً این شیء تغییرناپذیر (immutable) می‌باشد. بازگشایی (unboxing) نیز نسخه‌ای کپی از مقدار ذخیره‌شده را بازمی‌گرداند. تکرار عملیات بسته‌بندی و بازگشایی می‌تواند تأثیر منفی چشم‌گیری بر عملکرد داشته باشد؛ چراکه بسته‌بندی به‌صورت پویا اشیای جدیدی ایجاد می‌کند و بازگشایی، در صورتی که مقدار باکس‌شده دیگر استفاده نشود، باعث می‌شود آن اشیا برای بازیافت حافظه (garbage collection) در دسترس قرار گیرند. با این حال، بازیاب‌های حافظهٔ مدرن، مانند بازیاب پیش‌فرض Java HotSpot، می‌توانند اشیای کوتاه‌عمر را با کارایی بیشتری مدیریت کنند. بنابراین، در صورتی که اشیای باکس‌شده عمر کوتاهی داشته باشند، تأثیر آن‌ها بر عملکرد ممکن است چندان محسوس نباشد.در برخی زبان‌های برنامه‌نویسی، میان نوع‌های ابتداییِ بدون بسته‌بندی (unboxed primitives) و ارجاع به اشیای بسته‌بندی‌شدهٔ تغییری‌ناپذیر (immutable boxed objects)، برابری مستقیمی وجود دارد. در واقع، این امکان وجود دارد که تمامی نوع‌های ابتداییِ به‌کاررفته در یک برنامه با نوع‌های شیء بسته‌بندی‌شده جایگزین شوند. در حالی‌که انتساب از یک نوع ابتدایی به نوع ابتدایی دیگر، مقدار را کپی می‌کند، انتساب از یک ارجاع به شیء بسته‌بندی‌شده به ارجاع دیگر، تنها مقدار ارجاع را منتقل می‌کند؛ به‌گونه‌ای که هر دو ارجاع به یک شیء یکسان اشاره می‌کنند. با این حال، این مسئله مشکلی ایجاد نمی‌کند، زیرا این اشیاء تغییری‌ناپذیر هستند، و از نظر معنایی تفاوتی میان دو ارجاع به یک شیء یا ارجاع به دو شیء جداگانه با مقدار برابر وجود ندارد مگر آن‌که برابری فیزیکی (physical equality) مورد نظر باشد. برای تمام عملیات به‌جز انتساب، مانند عملیات ریاضی، مقایسه‌ای و منطقی، می‌توان ابتدا مقدار بسته‌بندی‌شده را بازگشایی کرد (unbox)، عملیات را انجام داد، و در صورت نیاز، نتیجه را مجدداً بسته‌بندی نمود (re-box). بنابراین، از نظر نظری، این امکان وجود دارد که نوع‌های ابتدایی به‌طور مستقیم ذخیره نشوندبسته‌بندی خودکار.اصطلاح «بسته‌بندی خودکار» (Autoboxing) به فرایندی اطلاق می‌شود که طی آن یک نوع ارجاعی (reference type) تنها از طریق تبدیل نوع (چه به‌صورت ضمنی و چه به‌صورت صریح) از یک نوع مقداری (value type) به‌دست می‌آید. در این حالت، کامپایلر به‌طور خودکار کدی را اضافه می‌کند که شیء مربوطه را ایجاد می‌نماید.به‌عنوان مثال، در نسخه‌های پیش از J2SE 5.0 از زبان جاوا، قطعه‌کد زیر قابل کامپایل نبود:Integer i = new Integer(9);Integer i = 9; // خطا در نسخه‌های پیش از 5.0!کامپایلرهای نسخه‌های پیش از 5.0 خط آخر را نمی‌پذیرفتند. codice_5 یک شیء ارجاعی (reference object) است و در ظاهر تفاوتی با نوع‌هایی مانند codice_23، codice_2 و غیره ندارد. برای تبدیل یک مقدار codice_4 به یک شیء codice_5، برنامه‌نویس مجبور بود شیء codice_5 را به‌صورت دستی ایجاد کند. اما از نسخهٔ J2SE 5.0 به بعد، کامپایلر این خط را می‌پذیرد و به‌طور خودکار آن را طوری بازنویسی می‌کند که شیئی از نوع codice_5 برای ذخیرهٔ مقدار ۹ ایجاد شود. این بدان معناست که از نسخهٔ J2SE 5.0 به بعد، نوشتن عبارتی مانند codice_29 ــ در حالی که codice_30 و codice_31 خودشان از نوع codice_5 باشند ــ قابل کامپایل است. در این حالت، codice_30 و codice_31 به‌صورت خودکار «بازگشایی» می‌شوند (unboxed)، مقادیر عددی آن‌ها با هم جمع می‌شود، و نتیجه به‌طور خودکار دوباره «بسته‌بندی» شده (autoboxed) و در متغیر codice_35 به‌صورت یک شیء جدید codice_5 ذخیره می‌شود. با این حال، نمی‌توان از عملگرهای مقایسه‌ای به همین صورت استفاده کرد؛ زیرا این عملگرها برای نوع‌های ارجاعی تعریف شده‌اند و تنها برابریِ ارجاع‌ها (references) را بررسی می‌کنند، نه مقدار درون آن‌ها را. برای مقایسهٔ مقدار در نوع‌های بسته‌بندی‌شده، همچنان باید آن‌ها را به‌صورت دستی بازگشایی کرد و مقادیر ابتدایی را مقایسه نمود، یا از متد codice_37 استفاده کرد.مثال دیگر: در نسخهٔ J2SE 5.0، برنامه‌نویس می‌تواند با مجموعه‌هایی مانند codice_1 طوری رفتار کند که گویی شامل مقادیر codice_4 هستند، نه اشیای codice_5. این موضوع با آنچه پیش‌تر گفته شد تناقضی ندارد؛ زیرا مجموعه همچنان تنها شامل ارجاع‌هایی به اشیای پویا است و نمی‌تواند نوع‌های ابتدایی را مستقیماً در خود نگه دارد. در واقع، نمی‌توان از codice_41 استفاده کرد، بلکه باید از codice_15 بهره برد. با این حال، کامپایلر به‌طور خودکار کد را به‌گونه‌ای بازنویسی می‌کند که لیست «بی‌سروصدا» اشیای بسته‌بندی‌شده را دریافت کند، در حالی که در کد منبع تنها به مقادیر ابتدایی اشاره شده است. برای مثال، برنامه‌نویس می‌تواند بنویسد codice_43 و تصور کند که مقدار ۳ از نوع codice_4 به لیست افزوده شده‌ است؛ اما در عمل، کامپایلر این خط را به شکل زیر بازنویسی می‌کند: codice_45.بازگشایی خودکار.در حالت «بازگشایی خودکار» (automatic unboxing)، کامپایلر به‌طور خودکار کدی اضافه می‌کند که مقدار را از شیء بسته‌بندی‌شده استخراج می‌کند؛ این کار ممکن است با فراخوانی یک متد روی آن شیء یا به روش‌های دیگر انجام شود.برای نمونه، در نسخه‌های پیش از J2SE 5.0 از زبان جاوا، قطعه‌کد زیر قابل کامپایل نبود:Integer k = new Integer(4);int l = k.intValue(); // همیشه مجاز استint m = k; // در گذشته خطا بود، اما اکنون مجاز استزبان #C از «بازگشایی خودکار» (automatic unboxing) به همان شکلی که در زبان جاوا پشتیبانی می‌شود، پشتیبانی نمی‌کند؛ زیرا در #C مجموعه‌ای مجزا از نوع‌های ابتدایی (primitive types) و نوع‌های شیء (object types) وجود ندارد. تمامی نوع‌هایی که در جاوا به‌صورت جداگانه به‌عنوان نوع ابتدایی و نوع شیء تعریف شده‌اند، در #C توسط کامپایلر به‌صورت خودکار به یکی از دو شکلِ «نوع مقداری» (value type) یا «نوع ارجاعی» (reference type) پیاده‌سازی می‌شوند.در هر دو زبان، «بسته‌بندی خودکار» به‌طور پیش‌فرض عملیات «پایین‌ریزی نوع» (downcast) را انجام نمی‌دهد؛ به‌عبارت دیگر، کد زیر قابل کامپایل نخواهد بود:object o = i; // بسته‌بندی(boxing)int j = o; // بازگشایی(boxing) - خطا!Console.WriteLine(j); // این خط اجرا نمی‌شود؛ نویسنده احتمالاً انتظار داشت خروجی "42" باشدجاوا:int i = 42;object o = i; // بسته‌بندی(boxing)int j = o; // بازگشایی(boxing) - خطا!System.out.println(j); // این خط اجرا نمی‌شود؛ نویسنده احتمالاً انتظار داشت خروجی "42" باشدبسته‌بندی در زبان Rust:.در زبان Rust، ساختاری به نام codice_46 وجود دارد:let number = Box::new(42);اگر قرار باشد مقدار به یک نخ (thread) دیگر منتقل شود، باید از ساختار codice_47 استفاده شود.کمک‌کننده‌های نوع (Type Helpers):.در زبان Modern Object Pascal، روشی دیگر برای انجام عملیات بر روی نوع‌های ساده وجود دارد که شباهت زیادی به باکسینگ (boxing) دارد و با عنوان «کمک‌کننده‌های نوع» ("type helpers") در FreePascal یا «کمک‌کننده‌های رکورد» ("record helpers") در Delphi و FreePascal (در حالت Delphi) شناخته می‌شود.گویش‌های اشاره‌شده، همگی از خانوادهٔ زبان‌های Object Pascal هستند که به کد بومی (native) کامپایل می‌شوند و از این رو برخی از قابلیت‌هایی را که در زبان‌هایی مانند #C و Java وجود دارد، پشتیبانی نمی‌کنند. از جملهٔ این قابلیت‌ها می‌توان به «استنباط نوع در زمان اجرا» (runtime type inference) برای متغیرهایی با نوع ایستا (strongly typed) اشاره کرد.uses sysutils; // این واحد شامل کمک‌کننده‌هایی برای نوع‌های ساده استvar x:integer=100; s:string;begin s:= x.ToString; writeln(s);end.