আমি কেন একটি ক্লাসটিকে বিমূর্ত শ্রেণি হিসাবে ঘোষণা করব?


40

আমি বাক্য গঠন জানি, বিমূর্ত শ্রেণীর জন্য প্রয়োগ বিধি এবং আমি একটি বিমূর্ত শ্রেণীর ব্যবহার জানতে চাই

বিমূর্ত শ্রেণিটি সরাসরি ইনস্ট্যান্ট করা যায় না তবে অন্যান্য শ্রেণি দ্বারা প্রসারিত করা যায়

এমন করে লাভ কী?

এটি কোনও ইন্টারফেস থেকে কীভাবে আলাদা?

আমি জানি যে একটি শ্রেণি একাধিক ইন্টারফেস বাস্তবায়ন করতে পারে তবে কেবল একটি বিমূর্ত শ্রেণি প্রসারিত করতে পারে। এটি কি কেবল ইন্টারফেস এবং বিমূর্ত শ্রেণীর মধ্যে পার্থক্য?

আমি একটি ইন্টারফেস ব্যবহার সম্পর্কে সচেতন। আমি জাভাতে এডাব্লুটিটির ইভেন্ট প্রতিনিধি মডেল থেকে শিখেছি।

কোন পরিস্থিতিতে আমার ক্লাসটি বিমূর্ত শ্রেণি হিসাবে ঘোষণা করা উচিত? এর সুবিধা কী?


14
এটি জিজ্ঞাসা করা হয়েছে, আপনি জানেন। একটি অনুসন্ধান এই জাতীয় মত অন্যান্য প্রশ্নের সন্ধান করবে। আপনার গুগল থেকে শুরু করা উচিত, যা আপনাকে স্ট্যাক ওভারফ্লোতে নিয়ে যাবে। এগুলির সবগুলিই সদৃশ: স্ট্যাকওভারফ্লো . com / search ? q=abstract+interface
এস .লট

1
"বিমূর্ত শ্রেণীর ব্যবহার তারা কেবল আলোচনা করে ... নিয়ম"। কি? "বিধি" এবং "ব্যবহার" এর মধ্যে কী আলাদা? আপনার সঠিক প্রশ্নটি উপায় দ্বারা জিজ্ঞাসা করা হয়েছিল। আমি জানি. আমি এর উত্তর দিয়েছি। তাকাতে থাকুন। কীভাবে অনুসন্ধান ব্যবহার করবেন তা শিখতে গুরুত্বপূর্ণ।
এস .লট

আমি বলতে চাইছি "কোন পরিস্থিতিতে আমার ক্লাসটি বিমূর্ত শ্রেণি হিসাবে ঘোষণা করা উচিত? এর সুবিধা কী?"
বৈভব জনি

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

আমি টেমপ্লেট পদ্ধতিটির প্যাটার্নটি একটি খুব শক্তিশালী এবং বিমূর্ত ক্লাসগুলির জন্য একটি ভাল ব্যবহারের ক্ষেত্রে খুঁজে পাই।
m3th0dman

উত্তর:


49

এই উত্তরটি একটি বিমূর্ত শ্রেণি এবং একটি ইন্টারফেসের মধ্যে পার্থক্য ব্যাখ্যা করার জন্য একটি ভাল কাজ করে তবে আপনার কেন একটি ঘোষণা করা উচিত তা তার উত্তর দেয় না

খাঁটি প্রযুক্তিগত দৃষ্টিকোণ থেকে কোনও শ্রেণিকে বিমূর্ত হিসাবে ঘোষণার প্রয়োজন হয় না ।

নিম্নলিখিত তিনটি শ্রেণী বিবেচনা করুন:

class Database { 
    public String[] getTableNames() { return null; } //or throw an exception? who knows...
}

class SqlDatabase extends Database { } //TODO: override getTableNames

class OracleDatabase extends Database { }  //TODO: override getTableNames

আপনি না আছে যখন আপনি এই প্রোগ্রাম লেখা হয়, আপনি টাইপ পারে: যদিও সেখানে তার বাস্তবায়ন সঙ্গে একটি সুস্পষ্ট সমস্যা হচ্ছে, ডাটাবেজ বর্গ বিমূর্ত করতে new Database()এবং এটি বৈধ হতে পারে, কিন্তু এটা কাজ না।

নির্বিশেষে, আপনি এখনও পলিমারফিজম পাবেন, যতক্ষণ না আপনার প্রোগ্রামটি কেবল তৈরি করে SqlDatabaseএবং OracleDatabaseউদাহরণ হিসাবে আপনি এই পদ্ধতি লিখতে পারেন:

public void printTableNames(Database database) {
    String[] names = database.getTableNames();
}

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

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

নিম্নলিখিত পদ্ধতিটি বিবেচনা করুন:

public void saveToDatabase(IProductDatabase database) {
     database.addProduct(this.getName(), this.getPrice());
}

databaseকোনও নির্দিষ্ট অবজেক্ট থেকে অবজেক্টটি উত্তরাধিকার সূত্রে এসেছে কিনা সে বিষয়ে আপনি চিন্তা করেন না , আপনি কেবল যত্নবান হন যে এটির কোনও addProductপদ্ধতি রয়েছে। সুতরাং এই ক্ষেত্রে আপনার ইন্টারফেসটি আপনার সমস্ত ক্লাসকে একই বেস শ্রেণীর উত্তরাধিকারী হওয়ার চেয়ে আরও উপযুক্ত better

কখনও কখনও দুজনের সংমিশ্রণটি খুব সুন্দরভাবে কাজ করে। উদাহরণ স্বরূপ:

abstract class RemoteDatabase implements IProductDatabase { 
    public abstract String[] connect();
    public abstract void writeRow(string col1, string col2);

    public void addProduct(String name, Double price) {
        connect();
        writeRow(name, price.toString());
    }
}

class SqlDatabase extends RemoteDatabase {
    //TODO override connect and writeRow
}

class OracleDatabase extends RemoteDatabase { 
    //TODO override connect and writeRow
}

class FileDatabase implements IProductDatabase {
    public void addProduct(String name, Double price) {
         //TODO: just write to file
    }
}

লক্ষ্য করুন যে কীভাবে কিছু কার্যকারিতা ভাগ করার জন্য কিছু ডেটাবেস রিমোটড্যাটাবেসেস থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় (যেমন একটি সারি লেখার আগে সংযোগ স্থাপন করা) তবে ফাইলডাটাবেসগুলি পৃথক শ্রেণি যা কেবল প্রয়োগ করে IProductDatabase


16

মিল

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

পার্থক্য

  1. ইন্টারফেস

    • সুপরিচিত পাবলিক কন্ট্রাক্ট, ধরণের দক্ষতা সংজ্ঞায়িত করুন
    • অনুভূমিক উত্তরাধিকার প্রদর্শনের জন্য প্রযোজ্য, যেমন উত্তরাধিকারের প্রথম স্তরে শাখা করা (উদাহরণস্বরূপ ডাটাবেস, পাঠ্য ফাইল, এক্সএমএল, এসওএপি ইত্যাদিতে লগিং সুবিধার সংজ্ঞা দিতে আইলগ)
    • সমস্ত সদস্য পাবলিক
    • বাস্তবায়নের অনুমতি নেই
    • উত্তরাধিকারী শিশুটির প্রয়োগের জন্য অনেক ইন্টারফেস থাকতে পারে
    • তৃতীয় পক্ষের সংহতকরণের জন্য দরকারী
    • নামকরণ সাধারণত আমার সাথে শুরু হয়
  2. বিমূর্ত শ্রেণি

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

এটা তোলে দ্বারা উত্তর খুঁজে আসলে সহজ সহজ গুগল ক্যোয়ারী


আপনি কি মেনা বাস্তবায়ন দ্বারা অনুমোদিত না? জাভা ক্লাস ইন্টারফেস প্রয়োগ করতে পারে।
সাজুউক

@ সাজুক এই লাইনটি একটি ইন্টারফেসকে বোঝায়। আপনি একটি ইন্টারফেসের মধ্যে একটি চুক্তির বাস্তবায়ন রাখতে পারবেন না। আপনার একটি বিমূর্ত শ্রেণিতে একটি চুক্তির ডিফল্ট প্রয়োগ হতে পারে।
ওলেক্সি

11

এটি কোনও ইন্টারফেস থেকে কীভাবে আলাদা?

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


এটি জাভা 8 এর জন্য সত্যই একটি আপডেট দরকার, যেখানে ডিফল্ট পদ্ধতিগুলি চালু হয়েছিল।
হাকন লাটভিট

8

বিমূর্ত ক্লাসগুলি "একটি" সম্পর্কগুলির জন্য এবং ইন্টারফেসগুলি "করতে পারে" এর জন্য।

বিমূর্ত ক্লাসগুলি আপনাকে বেস আচরণটি যুক্ত করতে দেয় যাতে প্রোগ্রামাররা আপনার নকশাটি অনুসরণ করতে বাধ্য করার সময় সমস্ত কিছুর কোড না করে।


3

গভীর প্রযুক্তিগত বিবরণ ছাড়াও - যেমন বিমূর্ত শ্রেণির জন্য কিছু পদ্ধতির প্রয়োগ ইত্যাদি, অর্থটির অর্থ এটি হ'ল:

ইন্টারফেসগুলি সাধারণ দক্ষতা সংজ্ঞায়িত করে - আইয়ানম্যারেবল সংজ্ঞা দেয়, যে শ্রেণিটি এই ইন্টারফেসটি প্রয়োগ করে তা গণনা করা যায়। এটি ক্লাস সম্পর্কে নিজেই কিছু বলে না।

বিমূর্ত (বা বেস) শ্রেণিগুলি আচরণকে সংজ্ঞায়িত করে - WebRequest HtpWebRequest ইত্যাদির মতো সমস্ত শিশু শ্রেণির একটি সাধারণ আচরণকে সংজ্ঞায়িত করে It এটি শ্রেণীর মূল অর্থ সংজ্ঞায়িত করে এবং এটির আসল উদ্দেশ্য - ওয়েব সংস্থান অ্যাক্সেস করা।


2

উইকিপিডিয়া এন্ট্রি

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

interface MyInterface1 {
  string getValue1();
}

interface MyInterface2 {
  string getValue2();
}

abstract class MyAbstractClass implements MyInterface1, MyInterface2{
  void printValues() {
    System.out.println("Value 1: " + getValue1() + ", Value 2: " + getValue2() + 
                       ", Value 3: " + getValue3());
  }

  protected abstract string getValue3();
}

class ImpClass extends MyAbstractClass {
  public string getValue1() {
    return "1";
  }

  public string getValue2() {
    return "2";
  }

  protected string getValue3() {
    return "3";
  }
}

এই উদাহরণে, MyAbstractClass একটি সর্বজনীন পদ্ধতি সরবরাহ করে যা তিনটি মানকেই মুদ্রণ করে। ইন ImpClass আপনার কাছ থেকে যথাক্রমে getValue1 এবং getValue2 বাস্তবায়ন প্রয়োজন MyInterface1 এবং MyInterface2 বিমূর্ত ক্লাস থেকে এবং getValue3।

Voila।

আরও কিছু দিক রয়েছে (ইন্টারফেস: কেবল পাবলিক পদ্ধতি, বিমূর্ত শ্রেণি: সুরক্ষিত বিমূর্ত এবং পাবলিক বিমূর্ত পদ্ধতি) তবে আপনি নিজের জন্য এটি পড়তে পারেন।

একটি চূড়ান্ত নোটে, একটি বিমূর্ত শ্রেণি যা কেবল বিমূর্ত পদ্ধতি সরবরাহ করে তা হ'ল "খাঁটি" বিমূর্ত বেস শ্রেণি, ওরফে, একটি ইন্টারফেস।


2
  • ইন্টারফেস - যখন কয়েকটি ক্লাস একটি এপিআই ভাগ করে দেয় (পদ্ধতির নাম এবং পরামিতি)
  • বিমূর্ত শ্রেণি - যখন কয়েকটি শ্রেণি একই কোড ভাগ করে (বাস্তবায়ন)

অন্য কথায়, আপনার একটি প্রশ্ন দিয়ে শুরু করা উচিত: "এই ক্লাসগুলি প্রয়োজনীয়ভাবে বাস্তবায়নটি ভাগ করে না, বা তাদের কেবল একটি সাধারণ ইন্টারফেস রয়েছে ?"

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

বাস্তবায়ন ভাগ করে নেওয়ার অন্যান্য উপায়ও রয়েছে, উদাহরণস্বরূপ সেই প্রয়োগের সাথে কোনও বস্তুকে আবদ্ধ করা (উদাহরণস্বরূপ কৌশল প্যাটার্নে)।


1

আপনি যখন বিকাশকারীকে (সম্ভবত নিজেকে) এটি ইনস্ট্যান্ট করার অনুমতি না চান তখন আপনি একটি শ্রেণীর বিমূর্ততা ঘোষণা করবেন, কারণ এটি কার্যকর হবে না বা তা বোঝায় না।

উদাহরণস্বরূপ, এমন একটি গেম বিবেচনা করুন যেখানে বিভিন্ন ধরণের গেম সত্তা রয়েছে। তারা সবাই বেস GameEntityবর্গ থেকে উত্তরাধিকারী হয় ।

abstract class GameEntity{

    int lifePoint, speed, damage;

    public attack(GameEntity target){ target.damage(damage); }

    public damage(int damageInflicted){ lifePoint -= damageInflicted - speed; }

    // etc...

}

এই শ্রেণিটি ঘোষিত হয়েছে abstractযেহেতু এটি তাত্পর্যপূর্ণ করার কোনও অর্থ হবে না। এটি গেম সত্তা এবং কিছু বৈশিষ্ট্যের জন্য কিছু ক্রিয়া ঘোষণা করে তবে এই শ্রেণীর কোথাও এই বৈশিষ্ট্যগুলির আরম্ভ করা হয় নি। এই শ্রেণিটি গেম সত্তাগুলির জন্য একটি টেম্পলেট হিসাবে কাজ করে, তবে এটি নিজের মতো করে এবং ঘোষিত হিসাবে ইনস্ট্যান্টেট করা নয় abstract

বিমূর্ত শ্রেণি এবং একটি ইন্টারফেসের মধ্যে ব্যবহারের পার্থক্য সম্পর্কে:

আমি এটি দেখতে পাচ্ছি, কোনও ইন্টারফেস হ'ল কিছু ভাষার একক-উত্তরাধিকার প্রক্রিয়া দ্বারা সীমাবদ্ধ না হয়ে পলিমারফিক আচরণ অর্জনের একটি উপায়।

উদাহরণ হিসাবে খেলায় ফিরে আসি। Enemyথেকে প্রাপ্ত একটি শ্রেণীর বিবেচনা করুন GameEntity। এই শ্রেণীর একটি পদ্ধতি আছে attackMeFromDistance(RangedAttacker attacker)। এই পদ্ধতিটি হ'ল সত্ত্বাকে দূর থেকে শত্রুকে আক্রমণ করার অনুমতি দেওয়ার জন্য to

আপনি দেখতে পাচ্ছেন, এই পদ্ধতিটি RangedAttackerপ্যারামিটার হিসাবে এক ধরণের নেয় । যাইহোক, সমস্ত গেম সত্তা ইতিমধ্যে উত্তরাধিকার সূত্রে প্রাপ্ত GameEntity। তারা অন্য শ্রেণি বাড়াতে পারে না।

ক্লাস নিন Mageএবং Archerউদাহরণস্বরূপ। আমরা উভয়কেই attackMeFromDistance(RangedAttacker attacker)পদ্ধতিতে প্যারামিটার হিসাবে গ্রহণ করার অনুমতি দিতে চাই , তবে তারা ইতিমধ্যে প্রাপ্ত GameEntity

এটি সমাধানের জন্য, আমরা একটি নতুন ইন্টারফেস তৈরি করি:

interface RangedAttacker{
    public void attackFromDistance();
}

এই ইন্টারফেসটি বাস্তবায়িত করে এমন একটি শ্রেণীর অবশ্যই attackFromDistance()পদ্ধতিটি বাস্তবায়ন করতে হবে এবং সুতরাং এটি নিশ্চিত করা হয় যে এটি আক্রমণ করার ক্ষমতা নিয়েছে। এর অর্থ হল যে attackMeFromDistanceপদ্ধতিটি এখন এই ইন্টারফেসটি প্রয়োগ করে এমন ক্লাসগুলি নিরাপদে গ্রহণ করতে পারে। সুতরাং সেই ইন্টারফেসটি তৈরি Mageএবং Archerপ্রয়োগ করা আমাদের সমস্যা সমাধান করে।

আমার কাছে এটি ইন্টারফেসের শক্তি।

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


0
  1. কিছু শ্রেণিতে (ব্যবসায়িক যুক্তি) খুব সাধারণ পদ্ধতি রয়েছে এমন সুযোগ রয়েছে। এবং বাকি পদ্ধতিগুলি পৃথক। এই ধরণের পরিস্থিতিতে আপনি একটি সাধারণ শ্রেণীর সমস্ত সাধারণ পদ্ধতি বাস্তবায়ন করতে পারেন এবং বাকীটিকে বিমূর্ত হিসাবে ঘোষণা করতে পারেন। তারপরে আপনার ক্লাসটি বিমূর্ত হিসাবে ঘোষণা করা উচিত।
  2. কখনও কখনও আপনি সরাসরি ক্লাসে অবজেক্ট তৈরি করার অনুমতি দেন না। এই ধরণের শ্রেণীর আপনাকে ক্লাসটি বিমূর্ত হিসাবে ঘোষণা করতে হবে।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.