"বাঁধাই করা" একটি পদ্ধতির নামটি একটি চলতি কোডের একাংশে সমাধান করার কাজকে বোঝায়। সাধারণত, ফাংশন কলটি সংকলন সময়ে বা লিংক সময়ে সমাধান করা যেতে পারে। স্ট্যাটিক বাইন্ডিং ব্যবহার করে ভাষার উদাহরণ সি:
int foo(int x);
int main(int, char**) {
printf("%d\n", foo(40));
return 0;
}
int foo(int x) { return x + 2; }
এখানে, foo(40)
সংকলক দ্বারা কলটি সমাধান করা যেতে পারে। এই প্রথম দিকে ইনলাইনিংয়ের মতো নির্দিষ্ট অপ্টিমাইজেশনের অনুমতি দেয়। সর্বাধিক গুরুত্বপূর্ণ সুবিধা হ'ল:
- আমরা টাইপ চেকিং করতে পারি
- আমরা অপ্টিমাইজেশন করতে পারি
অন্যদিকে, কিছু ভাষা শেষ সম্ভাব্য মুহুর্তে ফাংশন রেজোলিউশনকে পিছিয়ে দেয়। একটি উদাহরণ পাইথন, যেখানে আমরা উড়ন্ত চিহ্নগুলিকে নতুনভাবে সংজ্ঞা দিতে পারি:
def foo():
""""call the bar() function. We have no idea what bar is."""
return bar()
def bar():
return 42
print(foo()) # bar() is 42, so this prints "42"
# use reflection to overwrite the "bar" variable
locals()["bar"] = lambda: "Hello World"
print(foo()) # bar() was redefined to "Hello World", so it prints that
bar = 42
print(foo()) # throws TypeError: 'int' object is not callable
এটি দেরীতে বাইন্ডিংয়ের একটি উদাহরণ। যদিও এটি কঠোর প্রকারের পরীক্ষা করা অযৌক্তিকভাবে করা হয় (টাইপ চেকিং কেবল রানটাইম সময়ে করা যেতে পারে), এটি অনেক বেশি নমনীয় এবং আমাদের এমন ধারণাটি প্রকাশ করতে দেয় যা স্থির টাইপিং বা প্রাথমিক বাইন্ডিংয়ের সীমানায় প্রকাশ করা যায় না। উদাহরণস্বরূপ, আমরা রানটাইমে নতুন ফাংশন যুক্ত করতে পারি।
"স্থিতিশীল" ওওপি ভাষাগুলিতে সাধারণত প্রয়োগ করা হিসাবে পদ্ধতি প্রেরণ এই দুটি চরমের মধ্যে কোথাও রয়েছে: একটি শ্রেণি সামনে সমস্ত সমর্থিত ক্রিয়াকলাপের ধরণ ঘোষণা করে, তাই এগুলি স্ট্যাটিকালি পরিচিত এবং টাইপচেক করা যেতে পারে। তারপরে আমরা একটি সাধারণ লক লুক টেবিল (ভিটিবেল) তৈরি করতে পারি যা প্রকৃত বাস্তবায়নের দিকে নির্দেশ করে। প্রতিটি বস্তু একটি vtable একটি পয়েন্টার থাকে। প্রকারের সিস্টেমটি গ্যারান্টি দেয় যে আমরা যে কোনও বস্তু পেয়েছি তার উপযুক্ত ভ্যাটেবল থাকবে তবে এই অনুসন্ধান সারণীর মান কী তা সংকলন করার সময় আমাদের কোনও ধারণা নেই। অতএব, অবজেক্টগুলি চারপাশে ডেটা হিসাবে ফাংশনগুলি পাস করতে ব্যবহৃত হতে পারে (ওওপি এবং ফাংশন প্রোগ্রামিং সমতলের অর্ধেক কারণ)। ভ্যাটবিলগুলি সহজেই কোনও ভাষায় প্রয়োগ করা যেতে পারে যা ফাংশন পয়েন্টারগুলিকে সমর্থন করে, যেমন সি।
#define METHOD_CALL(object_ptr, name, ...) \
(object_ptr)->vtable->name((object_ptr), __VA_ARGS__)
typedef struct {
void (*sayHello)(const MyObject* this, const char* yourname);
} MyObject_VTable;
typedef struct {
const MyObject_VTable* vtable;
const char* name;
} MyObject;
static void MyObject_sayHello_normal(const MyObject* this, const char* yourname) {
printf("Hello %s, I'm %s!\n", yourname, this->name);
}
static void MyObject_sayHello_alien(const MyObject* this, const char* yourname) {
printf("Greetings, %s, we are the %s!\n", yourname, this->name);
}
static MyObject_VTable MyObject_VTable_normal = {
.sayHello = MyObject_sayHello_normal,
};
static MyObject_VTable MyObject_VTable_alien = {
.sayHello = MyObject_sayHello_alien,
};
static void sayHelloToMeredith(const MyObject* greeter) {
// we have no idea what the VTable contents of my object are.
// However, we do know it has a sayHello method.
// This is dynamic dispatch right here!
METHOD_CALL(greeter, sayHello, "Meredith");
}
int main() {
// two objects with different vtables
MyObject frank = { .vtable = &MyObject_VTable_normal, .name = "Frank" };
MyObject zorg = { .vtable = &MyObject_VTable_alien, .name = "Zorg" };
sayHelloToMeredith(&frank); // prints "Hello Meredith, I'm Frank!"
sayHelloToMeredith(&zorg); // prints "Greetings, Meredith, we are the Zorg!"
}
এই ধরণের পদ্ধতি দেখার জন্য "গতিশীল প্রেরণ" এবং কোথাও কোথাও প্রাথমিক বাইন্ডিং এবং দেরী বাইন্ডিংয়ের নামে পরিচিত। আমি ডায়নামিক মেথড প্রেরণকে ওওপি প্রোগ্রামিংয়ের কেন্দ্রীয় সংজ্ঞায়িত সম্পত্তি হিসাবে বিবেচনা করি, অন্য কোনও কিছু (যেমন এনক্যাপসুলেশন, সাব টাইপিং,…) গৌণ বলে বিবেচনা করে। এটি আমাদের কোডগুলিতে পলিমারফিজমটি প্রবর্তন করতে সক্ষম করে, এমনকি কোডের কোনও অংশে এটি পুনরায় সংবিধান না করে নতুন আচরণ যুক্ত করতে সক্ষম করে! সি উদাহরণে, যে কোনও নতুন vtable যুক্ত করতে এবং সেই vtable এর সাথে একটি বস্তু পাস করতে পারে sayHelloToMeredith()
।
যদিও এটি দেরী-ইশ বাঁধাই, এটি কে'র পক্ষপাতিত্বকারী "চরম দেরি বাঁধাই" নয়। ধারণামূলক মডেলটির পরিবর্তে "ফাংশন পয়েন্টারগুলির মাধ্যমে পদ্ধতি প্রেরণ", তিনি "বার্তা প্রেরণের মাধ্যমে পদ্ধতি প্রেরণ" ব্যবহার করেন। এটি একটি গুরুত্বপূর্ণ পার্থক্য কারণ বার্তা পাঠানো আরও সাধারণ। এই মডেলটিতে, প্রতিটি বস্তুর একটি ইনবক্স রয়েছে যেখানে অন্যান্য বস্তু বার্তা রাখতে পারে। রিসিভ করা অবজেক্ট তখন সেই বার্তাটি ব্যাখ্যা করার চেষ্টা করতে পারে। সর্বাধিক সুপরিচিত ওওপি সিস্টেমটি ডাব্লুডাব্লুডাব্লু। এখানে বার্তা হ'ল এইচটিটিপি অনুরোধ, এবং সার্ভারগুলি বস্তু।
উদাহরণস্বরূপ, আমি প্রোগ্রামার্স.স্ট্যাকেক্সেঞ্জ.সেট সার্ভারটি জিজ্ঞাসা করতে পারি GET /questions/301919/
। স্বরলিপি তুলনা করুন programmers.get("/questions/301919/")
। সার্ভারটি এই অনুরোধটি প্রত্যাখ্যান করতে পারে বা আমাকে একটি ত্রুটি ফেরত পাঠাতে পারে, বা এটি আমাকে আপনার প্রশ্নের উত্তর দিতে পারে।
বার্তা প্রেরণের শক্তিটি এটি খুব ভালভাবে স্কেল করে: কোনও ডেটা ভাগ করা হয় না (কেবল স্থানান্তরিত হয়), সবকিছু অ্যাসিনক্রোনালি ঘটতে পারে, এবং বস্তুগুলি তাদের পছন্দ মত বার্তাগুলির ব্যাখ্যা করতে পারে। এটি কোনও বার্তা ওওপি সিস্টেমকে সহজেই প্রসারণযোগ্য করে তোলে। আমি এমন বার্তা প্রেরণ করতে পারি যা প্রত্যেকে বুঝতে পারে না এবং আমার প্রত্যাশিত ফলাফল বা ত্রুটি ফিরে পায়। কোন বার্তাগুলি এটি প্রতিক্রিয়া জানাবে সেটিকে সামনে প্রকাশ করার দরকার নেই।
এটি বার্তা গ্রহণের উপর নির্ভুলতা বজায় রাখার দায়িত্ব রাখে, এটি একটি ধারণা যা এনক্যাপসুলেশন নামে পরিচিত। উদাহরণস্বরূপ, আমি কোনও HTTP সার্ভার থেকে কোনও HTTP বার্তার মাধ্যমে জিজ্ঞাসা না করে কোনও ফাইল পড়তে পারি না। এটি HTTP সার্ভারকে আমার অনুরোধটি প্রত্যাখ্যান করার অনুমতি দেয়, যেমন যদি আমার অনুমতি না থাকে। ছোট স্কেল ওওপিতে, এর অর্থ হ'ল আমার কাছে কোনও সামগ্রীর অভ্যন্তরীণ অবস্থাতে পঠন-লেখার অ্যাক্সেস নেই, তবে অবশ্যই সর্বজনীন পদ্ধতিতে যেতে হবে। এইচটিটিপি সার্ভারকে আমার কাছে কোনও ফাইল পরিবেশন করতে হবে না। এটি কোনও ডিবি থেকে ডায়নামিকভাবে উত্পন্ন সামগ্রী তৈরি হতে পারে। আসল ওওপি-তে কোনও বিষয়বস্তু কীভাবে বার্তাগুলির প্রতিক্রিয়া জানায় তা ব্যবহারকারীর নজরে না ফেলেই স্যুইচ করা যেতে পারে। এটি "প্রতিবিম্ব" এর চেয়ে শক্তিশালী তবে সাধারণত একটি সম্পূর্ণ মেটা-অবজেক্ট প্রোটোকল। উপরে আমার সি উদাহরণ রানটাইম প্রেরণ পদ্ধতি পরিবর্তন করতে পারে না।
প্রেরণ প্রক্রিয়াটি পরিবর্তন করার ক্ষমতাটি দেরীতে বাইন্ডিংকে বোঝায়, যেহেতু সমস্ত বার্তা ব্যবহারকারী-সংজ্ঞায়িত কোডের মাধ্যমে পাঠানো হয়। এবং এটি অত্যন্ত শক্তিশালী: একটি মেটা-অবজেক্ট প্রোটোকল দেওয়া, আমি ক্লাস, প্রোটোটাইপস, উত্তরাধিকার, বিমূর্ত শ্রেণি, ইন্টারফেস, বৈশিষ্ট্য, একাধিক উত্তরাধিকার, মাল্টি-ডিসপ্যাচ, দিক-ভিত্তিক প্রোগ্রামিং, প্রতিবিম্ব, দূরবর্তী পদ্ধতির অনুরোধ, প্রক্সি অবজেক্টস ইত্যাদি এমন কোনও ভাষায় যা এই বৈশিষ্ট্যগুলি দিয়ে শুরু হয় না। এই বিকশিত করার ক্ষমতাটি সি #, জাভা বা সি ++ এর মতো আরও স্থির ভাষা থেকে সম্পূর্ণ অনুপস্থিত।