স্ট্যাটিক বনাম জাভাতে গতিশীল বাঁধাই


104

আমি বর্তমানে আমার ক্লাসগুলির একটির জন্য একটি অ্যাসাইনমেন্ট করছি, এবং এটিতে, জাভা সিনট্যাক্স ব্যবহার করে, স্ট্যাটিক এবং ডায়নামিক বাইন্ডিংয়ের উদাহরণ দিতে হবে ।

আমি মৌলিক ধারণাটি বুঝতে পারি, স্থিতিশীল বাঁধাই সংকলনের সময় ঘটে এবং ডাইনামিক বাঁধাই রানটাইমের সময় ঘটে তবে তারা কীভাবে বিশেষভাবে কাজ করে তা আমি বুঝতে পারি না can't

আমি অনলাইনে স্ট্যাটিক বাইন্ডিংয়ের একটি উদাহরণ পেয়েছি যা এই উদাহরণ দেয়:

public static void callEat(Animal animal) {
    System.out.println("Animal is eating");
}

public static void callEat(Dog dog) {
    System.out.println("Dog is eating");
}

public static void main(String args[])
{
    Animal a = new Dog();
    callEat(a);
}

এবং এটি "প্রাণী খাচ্ছে" মুদ্রণ করবে কারণ স্ট্যাটিক বাঁধাইয়ের জন্য কল করার আহ্বান জানানো হয়েছেcallEat , তবে কেন এটিকে স্থির বাধ্যতামূলক বলে বিবেচনা করা হচ্ছে তা সম্পর্কে আমি নিশ্চিত নই ।

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



4
নোট করুন যে এখানে বিভিন্ন ধরণের ধারণা রয়েছে যা "বাইন্ডিং" হিসাবে উল্লেখ করা হয়। এই বিশেষ ক্ষেত্রে, এই ধরণের বাঁধাইয়ের জন্য (যার মধ্যে অনুরূপ তবে অভিন্ন পদ্ধতি "স্বাক্ষর" নয়) এর মধ্যে একটি সংকলক (যা "স্থিতিশীল" সিদ্ধান্ত নেয়, যেহেতু তারা রান সময়ে আলাদা হয় না) সিদ্ধান্ত নেয় যে প্যারামিটারটি একটি "এনিমেল" কারণ এটি "স্থির" ভ্যারিয়েবলের (স্ট্যাটিক) ধরণ।
হট লিকস

(এমন কিছু ভাষা রয়েছে যেখানে নির্দিষ্ট পদ্ধতির স্বাক্ষরের পছন্দ রানটাইম পর্যন্ত ছেড়ে দেওয়া হবে এবং কলইট (কুকুর) নির্বাচন করা হবে))
হট লিকস

উত্তর:


116

থেকে Javarevisited ব্লগ পোস্টে :

স্থিতিশীল এবং গতিশীল বাঁধাইয়ের মধ্যে কয়েকটি গুরুত্বপূর্ণ পার্থক্য এখানে রয়েছে:

  1. জাভাতে স্ট্যাটিক বাইন্ডিং সংকলনের সময় হয় যখন ডাইনামিক বাইন্ডিং রানটাইমের সময় ঘটে।
  2. private, finalএবং staticপদ্ধতি এবং ভেরিয়েবলগুলি স্ট্যাটিক বাঁধাই ব্যবহার করে এবং সংকলক দ্বারা বন্ড হয় যখন রানটাইম অবজেক্টের উপর ভিত্তি করে রানটাইম চলাকালীন ভার্চুয়াল পদ্ধতিগুলি বন্ড হয়।
  3. স্ট্যান্ডিক বাঁধাই বাঁধার জন্য তথ্য ব্যবহার করে Type( classজাভাতে) যখন ডায়নামিক বাঁধাই বাঁধাইয়ের সমাধান করতে অবজেক্টটি ব্যবহার করে।
  4. ওভারলোডেড পদ্ধতিগুলি স্ট্যাটিক বন্ডিং ব্যবহার করে বন্ড হয় যখন ওভাররাইড পদ্ধতিগুলি রানটাইমের সময় ডায়নামিক বাইন্ডিং ব্যবহার করে বন্ড হয়।

এখানে একটি উদাহরণ যা জাভাতে স্থির এবং গতিশীল উভয়কেই বুঝতে আপনাকে সহায়তা করবে।

জাভায় স্থির বাইন্ডিং উদাহরণ

public class StaticBindingTest {  
    public static void main(String args[]) {
        Collection c = new HashSet();
        StaticBindingTest et = new StaticBindingTest();
        et.sort(c);
    }
    //overloaded method takes Collection argument
    public Collection sort(Collection c) {
        System.out.println("Inside Collection sort method");
        return c;
    }
    //another overloaded method which takes HashSet argument which is sub class
    public Collection sort(HashSet hs) {
        System.out.println("Inside HashSet sort method");
        return hs;
    }
}

আউটপুট : সংগ্রহের বাছাইয়ের পদ্ধতি

জাভাতে ডায়নামিক বাঁধার উদাহরণ

public class DynamicBindingTest {   
    public static void main(String args[]) {
        Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
        vehicle.start(); //Car's start called because start() is overridden method
    }
}

class Vehicle {
    public void start() {
        System.out.println("Inside start method of Vehicle");
    }
}

class Car extends Vehicle {
    @Override
    public void start() {
        System.out.println("Inside start method of Car");
    }
}

আউটপুট: গাড়ির ভিতরে শুরু পদ্ধতি start



11
আমি এখনও পার্থক্যটি বুঝতে পারি না,
টেকনাজি

9
@ টেকনাজী স্ট্যাটিক বাইন্ডিংটি কেবল টাইপটি দেখায় (সমানর আগে যেমনটি থাকে যেমন কালেকশন সি = নতুন হ্যাশসেট (); সুতরাং যখন এটি হ্যাশসেট হয় তখন এটি কেবল সংগ্রহ সামগ্রীরূপে দেখা যাবে)। ডায়ানমিক বাইন্ডিং আসল অবজেক্টটিকে বিবেচনা করে (সমানগুলির পরে কী হয় তাই এটি আসলে এটির একটি হ্যাশসেট স্বীকৃতি দেয়)।
চিহ্নিত করুন

22

মেথড বডিটিতে একটি মেথড কল সংযুক্তি বাইন্ডিং হিসাবে পরিচিত। যেমন মৌলিক বলেছিলেন যে "স্ট্যাটিক বাঁধাই বাঁধার জন্য টাইপ (জাভাতে ক্লাস) তথ্য ব্যবহার করে যখন ডায়নামিক বাঁধাই বাঁধাইয়ের সমাধান করার জন্য অবজেক্টটি ব্যবহার করে।" সুতরাং এই কোড:

public class Animal {
    void eat() {
        System.out.println("animal is eating...");
    }
}

class Dog extends Animal {

    public static void main(String args[]) {
        Animal a = new Dog();
        a.eat(); // prints >> dog is eating...
    }

    @Override
    void eat() {
        System.out.println("dog is eating...");
    }
}

ফলাফলটি তৈরি করবে: কুকুর খাচ্ছে ... কারণ কোন পদ্ধতিটি ব্যবহার করতে হবে তা আবিষ্কার করতে এটি অবজেক্ট রেফারেন্স ব্যবহার করছে। যদি আমরা উপরের কোডটি এতে পরিবর্তন করি:

class Animal {
    static void eat() {
        System.out.println("animal is eating...");
    }
}

class Dog extends Animal {

    public static void main(String args[]) {

        Animal a = new Dog();
        a.eat(); // prints >> animal is eating...

    }

    static void eat() {
        System.out.println("dog is eating...");
    }
}

এটি উত্পাদন করবে: প্রাণী খাচ্ছে ... কারণ এটি একটি স্থির পদ্ধতি, সুতরাং এটি কোন স্থিতিশীল পদ্ধতিটি কল করতে হবে তা সমাধান করতে প্রকার (এই ক্ষেত্রে প্রাণী) ব্যবহার করছে। স্থির পদ্ধতিগুলির পাশাপাশি ব্যক্তিগত এবং চূড়ান্ত পদ্ধতিগুলি একই পদ্ধতির ব্যবহার করে।


4
কেন জাভা ছাড় করতে পারে না যে aআসলে একটি Dogসংকলন সময়ে?
মিন নাঘিয়া

4

সংকলক কেবল জানে যে "ক" এর ধরণ Animal; এটি সংকলনের সময়ে ঘটে, যার কারণে এটিকে স্ট্যাটিক বাইন্ডিং (মেথড ওভারলোডিং) বলা হয়। তবে এটি যদি গতিশীল বাঁধাই হয় তবে এটি Dogক্লাস পদ্ধতিটিকে কল করবে । এখানে গতিশীল বাঁধাইয়ের একটি উদাহরণ is

public class DynamicBindingTest {

    public static void main(String args[]) {
        Animal a= new Dog(); //here Type is Animal but object will be Dog
        a.eat();       //Dog's eat called because eat() is overridden method
    }
}

class Animal {

    public void eat() {
        System.out.println("Inside eat method of Animal");
    }
}

class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("Inside eat method of Dog");
    }
}

আউটপুট: কুকুরের ভিতরে খাওয়ার পদ্ধতি


এটি কি "স্থির প্রসঙ্গ থেকে কোনও স্থিতিশীল শ্রেণি / পদ্ধতিটি উল্লেখ করতে পারে না" এর মতো সংকলন ত্রুটি ফেলবে না? আমি সর্বদা এটির সাথে বিভ্রান্ত থাকি, মনে রাখি যে মূলটি স্থির। আগাম ধন্যবাদ.
আম্নোর

4

স্থির এবং গতিশীল বাঁধাই আসলে কীভাবে কাজ করে তা বোঝার জন্য ? বা কীভাবে তারা সংকলক এবং জেভিএম দ্বারা চিহ্নিত হয়?

আসুন নীচের উদাহরণটি নেওয়া যাক যেখানে Mammalকোনও প্যারেন্ট ক্লাস যেখানে একটি পদ্ধতি রয়েছে speak()এবং Humanশ্রেণিটি প্রসারিত হয় Mammal, সেই speak()পদ্ধতিটি ওভাররাইড করে এবং তারপরে আবার এটি দিয়ে ওভারলোড হয় speak(String language)

public class OverridingInternalExample {

    private static class Mammal {
        public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
    }

    private static class Human extends Mammal {

        @Override
        public void speak() { System.out.println("Hello"); }

        // Valid overload of speak
        public void speak(String language) {
            if (language.equals("Hindi")) System.out.println("Namaste");
            else System.out.println("Hello");
        }

        @Override
        public String toString() { return "Human Class"; }

    }

    //  Code below contains the output and bytecode of the method calls
    public static void main(String[] args) {
        Mammal anyMammal = new Mammal();
        anyMammal.speak();  // Output - ohlllalalalalalaoaoaoa
        // 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

        Mammal humanMammal = new Human();
        humanMammal.speak(); // Output - Hello
        // 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

        Human human = new Human();
        human.speak(); // Output - Hello
        // 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V

        human.speak("Hindi"); // Output - Namaste
        // 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
    }
}

যখন আমরা উপরের কোডটি সংকলন করি এবং বাইটকোড ব্যবহার করে দেখার চেষ্টা javap -verbose OverridingInternalExampleকরি, আমরা দেখতে পাই যে সংকলকটি একটি ধ্রুবক সারণী উত্পন্ন করে যেখানে এটি প্রোগ্রামের জন্য প্রতিটি পদ্ধতি কল এবং বাইট কোডের জন্য পূর্ণসংখ্যা কোড নির্ধারণ করে যা আমি নিজেই প্রোগ্রামটিতে অন্তর্ভুক্ত করেছি এবং অন্তর্ভুক্ত করেছি ( প্রতিটি পদ্ধতি কল নীচের মন্তব্য দেখুন)

প্রোগ্রাম বাইটকোড

উপরের কোড দিকে তাকিয়ে আমরা যে bytecodes দেখতে পারেন humanMammal.speak(), human.speak()এবং human.speak("Hindi")সম্পূর্ণ ভিন্ন হয় ( invokevirtual #4, invokevirtual #7, invokevirtual #9) কারণ কম্পাইলার যুক্তি তালিকা এবং বর্গ রেফারেন্স উপর ভিত্তি করে তাদের মধ্যে পার্থক্য করতে সক্ষম হয়। কারণ এগুলি সমস্তই সংকলনের সময়ে স্থিরভাবে সমাধান হয়ে যায় সেজন্যই মেথড ওভারলোডিং স্ট্যাটিক পলিমারফিজম বা স্ট্যাটিক বাইন্ডিং হিসাবে পরিচিত ।

তবে বাইটকোড anyMammal.speak()এবং humanMammal.speak()একই ( invokevirtual #4) কারণ সংকলক অনুসারে উভয় পদ্ধতি Mammalরেফারেন্সে ডাকা হয় ।

সুতরাং এখন প্রশ্ন আসে যদি উভয় পদ্ধতির কলগুলিতে একই বাইটোকোড থাকে তবে জেভিএম কীভাবে কল করবে যে পদ্ধতিটি কল করতে হবে?

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

জাভাতে, প্রতিটি রেফারেন্স ভেরিয়েবল দুটি লুকানো পয়েন্টার ধারণ করে

  1. টেবিলের জন্য একটি পয়েন্টার যা আবার বস্তুর পদ্ধতি এবং শ্রেণি অবজেক্টের একটি পয়েন্টার ধারণ করে। যেমন [কথা (), কথা (স্ট্রিং) শ্রেণি অবজেক্ট]
  2. Object বস্তুর ডেটা যেমন উদাহরণ ভেরিয়েবলের মানগুলির জন্য হিপগুলিতে বরাদ্দ হওয়া মেমোরিটির একটি পয়েন্টার।

সুতরাং সমস্ত অবজেক্ট রেফারেন্স অপ্রত্যক্ষভাবে একটি টেবিলের রেফারেন্স ধরে রাখে যা সেই বস্তুর সমস্ত পদ্ধতি রেফারেন্স ধারণ করে। জাভা এই ধারণাটি সি ++ থেকে ধার নিয়েছে এবং এই টেবিলটি ভার্চুয়াল টেবিল (vtable) হিসাবে পরিচিত।

একটি ভেটেবল হ'ল কাঠামোর মতো একটি অ্যারে যা ভার্চুয়াল পদ্ধতির নাম এবং অ্যারে সূচকগুলিতে তাদের রেফারেন্স ধারণ করে। JVM ক্লাসটি মেমরিতে লোড করলে প্রতি ক্লাসে কেবল একটি vtable তৈরি করে।

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

কারণ এগুলি সমস্তই কেবল রানটাইম এ সমাধান হয়ে যায় এবং রানটাইম সময়ে জেভিএম জানতে পারে যে কোন পদ্ধতিটি চালু করতে হবে, সে কারণেই মেথড ওভাররাইডিং ডায়নামিক পলিমারফিজম বা কেবল পলিমারফিজম বা ডায়নামিক বাইন্ডিং হিসাবে পরিচিত ।

আপনি এটি আমার নিবন্ধে আরও বিশদটি পড়তে পারেন কীভাবে জেভিএম অভ্যন্তরীণভাবে ওভারলোডিং এবং ওভাররাইডিং পদ্ধতিটি পরিচালনা করে


2

সংকলকগুলি ডিজাইন করার সময় স্থিতিশীল এবং গতিশীল বাঁধার মধ্যে তিনটি প্রধান পার্থক্য রয়েছে এবং কীভাবে ভেরিয়েবল এবং পদ্ধতি রানটাইম পরিবেশে স্থানান্তরিত হয় । এই পার্থক্যগুলি নিম্নরূপ:

স্ট্যাটিক বাইন্ডিং : স্থির বাইন্ডিংয়ে নিম্নলিখিত তিনটি সমস্যা নিয়ে আলোচনা করা হয়:

  • একটি পদ্ধতির সংজ্ঞা

  • নামের ঘোষণা (পরিবর্তনশীল ইত্যাদি)

  • ঘোষণার সুযোগ

ডায়নামিক বাইন্ডিং : ডায়নামিক বাইন্ডিংয়ে আসা তিনটি সমস্যা নিম্নলিখিত হিসাবে রয়েছে:

  • একটি প্রক্রিয়া সক্রিয়করণ

  • একটি নাম বাঁধাই

  • একটি বাঁধাইয়ের লাইফটাইম


1

অভিভাবক এবং শিশু শ্রেণিতে স্থির পদ্ধতি সহ: স্ট্যাটিক বাঁধাই

public class test1 {   
    public static void main(String args[]) {
        parent pc = new child(); 
        pc.start(); 
    }
}

class parent {
    static public void start() {
        System.out.println("Inside start method of parent");
    }
}

class child extends parent {

    static public void start() {
        System.out.println("Inside start method of child");
    }
}

// Output => Inside start method of parent

গতিশীল বাঁধাই:

public class test1 {   
    public static void main(String args[]) {
        parent pc = new child();
        pc.start(); 
    }
}

class parent {
   public void start() {
        System.out.println("Inside start method of parent");
    }
}

class child extends parent {

   public void start() {
        System.out.println("Inside start method of child");
    }
}

// Output => Inside start method of child

0

এখানে সমস্ত উত্তর সঠিক তবে আমি অনুপস্থিত এমন কিছু যুক্ত করতে চাই। আপনি যখন কোনও স্ট্যাটিক পদ্ধতিকে ওভাররাইড করছেন তখন মনে হয় আমরা এটির উপর চাপ দিচ্ছি তবে বাস্তবে এটি মেথড ওভাররাইড নয়। পরিবর্তে এটিকে বলা হয় মেথড হিডিং। স্ট্যাটিক পদ্ধতি না পারেন, জাভা ইন্সটল করা।

নীচের উদাহরণে দেখুন:

class Animal {
    static void eat() {
        System.out.println("animal is eating...");
    }
}

class Dog extends Animal {

    public static void main(String args[]) {

        Animal a = new Dog();
        a.eat(); // prints >> animal is eating...

    }

    static void eat() {
        System.out.println("dog is eating...");
    }
}

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

আমার উত্তরটি সমর্থন করার জন্য আমি নীচের লিঙ্কটি পেয়েছি: https://youtu.be/tNgZpn7AeP0


0

সংকলন-সময়ে স্থির বাইন্ডিং ধরণের অবজেক্টের ক্ষেত্রে নির্ধারিত হয় যখন ডাইনামিক বাইন্ডিংয়ের মধ্যে অবজেক্টের রানটাইম নির্ধারিত হয়।



class Dainamic{

    void run2(){
        System.out.println("dainamic_binding");
    }

}


public class StaticDainamicBinding extends Dainamic {

    void run(){
        System.out.println("static_binding");
    }

    @Override
    void run2() {
        super.run2();
    }

    public static void main(String[] args) {
        StaticDainamicBinding st_vs_dai = new StaticDainamicBinding();
        st_vs_dai.run();
        st_vs_dai.run2();
    }

}

-3

কারণ সংকলক সংকলন সময়ে বাধ্যতামূলক জানে। উদাহরণস্বরূপ, আপনি যদি কোনও ইন্টারফেসে কোনও পদ্ধতিতে প্রার্থনা করেন, তবে সংকলকটি জানতে পারে না এবং রানটাইমগুলিতে বাইন্ডিংটি সমাধান করা হয় কারণ এতে একটি পদ্ধতি থাকা প্রকৃত অবজেক্টটি বেশ কয়েকটির মধ্যে একটি হতে পারে। সুতরাং এটি রানটাইম বা গতিশীল বাঁধাই।

আপনার অনুরোধটি সংকলনের সময় প্রাণী শ্রেণিতে আবদ্ধ কারণ আপনি প্রকারটি নির্দিষ্ট করেছেন। আপনি যদি সেই পরিবর্তনশীল অন্য কোথাও অন্য পদ্ধতিতে পাস করেন তবে কোনটিই জানতে পারবে না (আপনি এটি লিখেছেন বলেই আপনাকে বাদ দিয়ে) এটি প্রকৃত শ্রেণিটি কী হবে। একমাত্র সূত্রটি ঘোষিত ধরণের প্রাণী Animal


4
সত্য না. আপনি যদি কোনও ইন্টারফেসে কল করে থাকেন তবে সংকলকটি ঠিক একই সিদ্ধান্ত নেবে।
হট লিক্স

@ হটলিক্স ঠিক কি হিসাবে একই সিদ্ধান্ত? যদি আপনি কোনও ইন্টারফেসে একটি foo (স্ট্রিং str) পদ্ধতি চাওয়ার জন্য একটি ক্লাস সংকলন করেন তবে সংকলক সংকলনের সময় জানতে পারবেন না foo (স্ট্রিং str) পদ্ধতিটি কোন শ্রেণীর দ্বারা প্রবর্তন করা উচিত। কেবল রানটাইমের সময় পদ্ধতিটির অনুরোধটি একটি নির্দিষ্ট শ্রেণি প্রয়োগের জন্য আবদ্ধ হতে পারে।
হারুন

তবে নির্দিষ্ট পদ্ধতির স্বাক্ষরের স্থির বাধ্যবাধকতা এখনও ঘটবে। সংকলকটি এখনও কলইট (কুকুর) এর উপরে কল ইট (প্রাণী) বাছাই করবে।
হট লিক্স

পছন্দ করুন সম্ভবত এটি আমার বিভ্রান্তিকর ছিল: ডিআই এটির সাথে একটি ইন্টারফেসের সাথে অনুরোধ করার সাথে তুলনা করে যে সংকলনের সময় সংকলক জানতে পারে না আপনি আসলে কোনও আলাদা সাবক্লাস / বাস্তবায়ন ইনস্ট্যান্ট করেছেন কিনা।
অ্যারন

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