সি-তে কম্পাইল-টাইম এনক্যাপসুলেশন কী?


9

আমি যখন সি ওভার সি এর সুবিধাগুলি নিয়ে গবেষণা করছিলাম তখন আমি এই অনুচ্ছেদটি পেরিয়ে এসেছি:

এনক্যাপসুলেশন করার সি এর স্ট্যান্ডার্ড উপায় হ'ল একটি স্ট্রাক্ট ঘোষণা এবং কেবল ফাংশনের মাধ্যমে তার ডেটা অ্যাক্সেসের অনুমতি দেওয়া। এই পদ্ধতিটি সংকলন টাইম এনক্যাপসুলেশন তৈরি করে। সংকলন সময় এনক্যাপসুলেশন আমাদের ক্লায়েন্ট কোড (আমাদের ইন্টারফেস ব্যবহার করে অন্যান্য কোড) এর সংশোধন ছাড়াই ডেটা স্ট্রাকচার সদস্যদের পরিবর্তন করতে দেয় allows অন্যদিকে এনক্যাপসুলেশন সি ++ করার স্ট্যান্ডার্ড পদ্ধতিতে (ক্লাস ব্যবহার করে) ব্যক্তিগত সদস্যের ভেরিয়েবলগুলি যুক্ত বা অপসারণ করার সময় ক্লায়েন্ট কোডটি পুনরায় সংশোধন করা দরকার।

আমি বুঝতে পারি যে কীভাবে এগিয়ে স্ট্রাক্ট ঘোষণা করা এবং ফাংশনের মাধ্যমে এর সদস্যদের অ্যাক্সেস করা স্ট্রাক্টের প্রয়োগের বিশদটি গোপন করে। আমি যা বুঝতে পারি না তা হ'ল এই লাইনটি:

সংকলন সময় এনক্যাপসুলেশন আমাদের ক্লায়েন্ট কোড (আমাদের ইন্টারফেস ব্যবহার করে অন্যান্য কোড) এর সংশোধন ছাড়াই ডেটা স্ট্রাকচার সদস্যদের পরিবর্তন করতে দেয় allows

কোন পরিস্থিতিতে এটি প্রযোজ্য?


মূলত, এটি structএকটি কালো বাক্স যা অজানা ইন্টার্নালগুলি সহ। যদি ক্লায়েন্ট ইন্টার্নালগুলি না জানে, এটি কখনই সরাসরি তাদের অ্যাক্সেস করতে পারে না এবং আপনি ইচ্ছামত এগুলি পরিবর্তন করতে পারেন। এটি ওওপিতে এনক্যাপসুলেশনের অনুরূপ। অভ্যন্তরীণগুলি ব্যক্তিগত হয় এবং আপনি কেবল সর্বজনীন পদ্ধতি ব্যবহার করে অবজেক্টটি পরিবর্তন করেন।
সুলতান

এই সবসময় সত্য নয়। আপনি যদি কোনও কাঠামোর সদস্য যুক্ত / সরানোর সিদ্ধান্ত নেন তবে আপনি এর আকার পরিবর্তন করুন। এর জন্য ক্লায়েন্ট কোডটি পুনরায় সংশোধন করা প্রয়োজন।
ডার্কআটম

2
পছন্দ করুন যদি ক্লায়েন্ট সামগ্রীগুলি (একটি অস্বচ্ছ গঠন) জানেন না, তবে এটি এর আকারটি জানে না, তাই আকার পরিবর্তন করা কোনও সমস্যা নয়।
অ্যাড্রিয়ান মোল

1
@ ডার্কআটম: কেবল কার্যের মাধ্যমে কোনও কাঠামোতে অ্যাক্সেসের অনুমতি দেওয়াতে কেবল ফাংশনের মাধ্যমে বরাদ্দ অন্তর্ভুক্ত। গ্রন্থাগারটি কোনও কাঠামো বরাদ্দ করার জন্য একটি ফাংশন সরবরাহ করবে এবং ক্লায়েন্টটি কখনই তার আকার জানতে পারে না। আকার পরিবর্তন করার জন্য ক্লায়েন্টকে পুনরায় সংশোধনের প্রয়োজন হয় না।
এরিক পোস্টপিশিল

3
মনে রাখবেন যে প্রযুক্তিগতভাবে এটি "সি ওভার সি ++ এর সুবিধা নয়" যেমন আপনি সি ++ তে একই ধারণাটি প্রয়োগ করতে পারেন (এবং প্রায়শই করতে পারেন)। দেখুন "pimpl" বাগ্ধারা
ব্যবহারকারী 4815162342

উত্তর:


4

একটি সম্ভাব্য বাস্তব-জগতের পরিস্থিতি যেখানে এটি ঘটবে, যখন হার্ড-ডিস্কের স্থান খুব সীমাবদ্ধ ছিল এমন সময়ে লেখা একটি ডাটাবেস লাইব্রেরি যখন একটি বছরের 'বছর' ক্ষেত্রটি সংরক্ষণ করার জন্য একক বাইট ব্যবহার করে (যেমন 11-NOV-1973 73বছরের জন্য হবে )। তবে, যখন 2000 বছরটি এসেছিল, এটি আর পর্যাপ্ত হবে না এবং বছরটি তখন একটি সংক্ষিপ্ত (16-বিট) পূর্ণসংখ্যা হিসাবে সংরক্ষণ করা হত। এই লাইব্রেরির জন্য প্রাসঙ্গিক (অনেক সরলীকৃত) শিরোনাম এটি হতে পারে:

// dbEntry.h
typedef struct _dbEntry dbEntry;

dbEntry* CreateDBE(int day, int month, int year, int otherData);
void DeleteDBE(dbEntry* entry);
int GetYear(dbEntry* entry);

এবং একটি 'ক্লায়েন্ট' প্রোগ্রামটি হ'ল:

#include <stdio.h>
#include "dbEntry.h"

int main()
{
    int dataBlob = 42;
    dbEntry* test = CreateDBE(17, 11, 2019, dataBlob);
    //...
    int year = GetYear(test);
    printf("Year = %d\n", year);
    //...
    DeleteDBE(test);
    return 0;
}

'আসল' বাস্তবায়ন:

#include <stdlib.h>
#include "dbEntry.h"

struct _dbEntry {
    unsigned char d;
    unsigned char m;
    unsigned char y;    // Fails at Y2K!
    int dummyData;
};

dbEntry* CreateDBE(int day, int month, int year, int otherData)
{
    dbEntry* local = malloc(sizeof(dbEntry));
    local->d = (unsigned char)(day);
    local->m = (unsigned char)(month);
    local->y = (unsigned char)(year % 100);
    local->dummyData = otherData;
    return local;
}

void DeleteDBE(dbEntry* entry)
{
    free(entry);
}

int GetYear(dbEntry* entry)
{
    return (int)(entry->y);
}

তারপরে, ওয়াই 2 কে এর কাছে, এই প্রয়োগকারী ফাইলটি নীচে পরিবর্তন করা হবে (বাকি সমস্ত কিছুই আউটচুড রেখে দেওয়া হবে):

struct _dbEntry {
    unsigned char d;
    unsigned char m;
    unsigned short y;   // Can now differentiate 1969 from 2069
    int dummyData;
};

dbEntry* CreateDBE(int day, int month, int year, int otherData)
{
    dbEntry* local = malloc(sizeof(dbEntry));
    local->d = (unsigned char)(day);
    local->m = (unsigned char)(month);
    local->y = (unsigned short)(year);
    local->dummyData = otherData;
    return local;
}

যখন নতুন (Y2K- নিরাপদ) সংস্করণটি ব্যবহার করার জন্য ক্লায়েন্টকে আপডেট করার প্রয়োজন হবে তখন কোনও কোড পরিবর্তন করার প্রয়োজন হবে না। আসলে, আপনাকে এমনকি পুনরায় সংকলন করতে হবে না: কেবলমাত্র আপডেট হওয়া অবজেক্ট লাইব্রেরিতে পুনরায় সংযোগ করা (যদি এটি হয় তবে) যথেষ্ট হতে পারে


2

দ্রষ্টব্য: নীচের তালিকাটি অব্যক্ত নয়। সম্পাদনা স্বাগত!

প্রযোজ্য পরিস্থিতিতে অন্তর্ভুক্ত:

  • মাল্টি-মডিউল অ্যাপ্লিকেশনগুলি যেখানে আপনি কোনও কারণে পুনঃসংশোধন চান না।
  • লাইব্রেরিতে ব্যবহৃত কাঠামো যেখানে আপনি লাইব্রেরির ব্যবহারকারীদের প্রতিবার (প্রকাশিত) কাঠামো পরিবর্তন করার সময় পুনরায় সংকলন করতে বাধ্য করতে চান না।
  • বিভিন্ন প্ল্যাটফর্মগুলিতে মডিউলটি কাজ করে এমন কাঠামোতে বিভিন্ন উপাদান রয়েছে।

এই ধরণের সর্বাধিক পরিচিত কাঠামোটি FILE। আপনি কেবল কল করুন fopen()এবং সফল হলে একটি পয়েন্টার পান। এই পয়েন্টারটি পরে একে অপরের হাতে ফাংশন হস্তান্তর করা হয় যা ফাইলগুলিতে কাজ করে। তবে আপনি জানেন না - এবং আপনি জানতে চান না - বিশদ যেমন অন্তর্ভুক্ত উপাদান এবং আকার।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.