কেন স্পষ্টভাবে ইন্টারফেস বাস্তবায়ন?


122

সুতরাং, স্পষ্টভাবে একটি ইন্টারফেস বাস্তবায়নের জন্য ভাল ব্যবহারের ক্ষেত্রে কী?

ক্লাস ব্যবহারকারী লোকদের ইন্টেলিসেন্সে all সমস্ত পদ্ধতি / বৈশিষ্ট্যগুলি দেখার দরকার নেই তা কেবল তাই?

উত্তর:


146

আপনি যদি একই পদ্ধতি এবং বিভিন্ন বাস্তবায়ন উভয়ই দুটি ইন্টারফেস প্রয়োগ করেন তবে আপনাকে সুস্পষ্টভাবে বাস্তবায়ন করতে হবে।

public interface IDoItFast
{
    void Go();
}
public interface IDoItSlow
{
    void Go();
}
public class JustDoIt : IDoItFast, IDoItSlow
{
    void IDoItFast.Go()
    {
    }

    void IDoItSlow.Go()
    {
    }
}

হ্যাঁ ঠিক এটি EIMI সমাধান করে এমন একটি ঘটনা I এবং অন্যান্য পয়েন্টগুলি "মাইকেল বি" উত্তর দ্বারা আবৃত রয়েছে।
ক্রিপ্টেড

10
দুর্দান্ত উদাহরণ। ইন্টারফেস / শ্রেণীর নাম পছন্দ! :-)
ব্রায়ান রজার্স

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

4
@ মাইক ইন্টারফেসগুলি কিছু এপিআই বা দুটি পৃথক পৃথক API এর অন্তর্গত হতে পারে। হয়তো প্রেম একটি বিট এখানে অতিরঞ্জিত কিন্তু আমি অন্তত আনন্দিত স্পষ্ট বাস্তবায়ন উপলভ্য যার এমন হতে চাই হয়।
টবিএমসিএনএমবি

@ ব্রায়ানরোগার্স এবং পদ্ধতির নামগুলিও ;-)
наđошƒаӽ:০৪

66

অ-পছন্দসই সদস্যটিকে আড়াল করতে এটি দরকারী। উদাহরণস্বরূপ, যদি আপনি উভয়ই বাস্তবায়ন করেন IComparable<T>এবং লোকেদের বোঝা না দেয় যে আপনি বিভিন্ন ধরণের অবজেক্টের তুলনা করতে পারেন IComparableতবে সাধারণত ওভারলোডটি আড়াল করা খুব ভাল IComparable। একইভাবে, কিছু ইন্টারফেস সিএলএস-সম্মতিযুক্ত নয়, যেমন IConvertible, তাই যদি আপনি স্পষ্টভাবে ইন্টারফেসটি প্রয়োগ না করেন, তবে সিএলএস সম্মতি প্রয়োজন এমন ভাষার শেষ ব্যবহারকারীরা আপনার অবজেক্টটি ব্যবহার করতে পারবেন না। (ছাত্রলীগের প্রয়োগকারীরা আদিমদের আইকনভার্টেবল সদস্যদের গোপন না রাখলে খুব বিপর্যয়কর হবে :))

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

void SomeMethod<T>(T obj) where T:IConvertible

আপনি যখন এটি পাস করেন তখন কোনও ইন্টার বক্স করবে না।


1
আপনার প্রতিবন্ধকতায় টাইপো রয়েছে। পরিষ্কার করতে, উপরের কোডটি কাজ করে। এটি ইন্টারফেসে পদ্ধতি স্বাক্ষরের প্রাথমিক ঘোষণায় থাকা দরকার। মূল পোস্টটি এটি নির্দিষ্ট করে নি। এছাড়াও, যথাযথ বিন্যাসটি হ'ল "সামড মেহহটড <টি> (টি আপত্তি) যেখানে টি: আইকনভার্টিভেবল Note দ্রষ্টব্য,") "এবং" যেখানে "থাকা উচিত নয় এর মধ্যে একটি অতিরিক্ত কোলন রয়েছে still ব্যয়বহুল বক্সিং এড়ানোর জন্য জেনেরিক্স
জ্যাক জান্নসেন

1
হাই মাইকেল বি। সুতরাং স্ট্রিং বাস্তবায়নে কেন .NET সেখানে আইকাম্পারেবলের পাবলিক বাস্তবায়ন: পাবলিক ইনপুট তুলনা করুন (বস্তুর মান) {যদি (মান == নাল) {ফেরত 1; } যদি (! (মানটি স্ট্রিং হয়)) {নতুন আর্গুমেন্টএক্সসেপশন (পরিবেশ.গেটআরসোর্সস্ট্রিং ("আরগ_মাস্টবস্ট্রিং")) নিক্ষেপ করুন; } String.Compare (এই, (স্ট্রিং) মান, স্ট্রিংকম্পায়ারেন্স.ক্রেনচারাল কালচার) ফেরত দিন; } ধন্যবাদ!
zzfima

stringজেনেরিকগুলির আগে প্রায় ছিল এবং এই অনুশীলন প্রচলিত ছিল। .NET 2 যখন এলো তখন তারা জনসাধারণের ইন্টারফেসটি ভেঙে ফেলতে চায়নি stringতাই তারা এটি নিরাপদে রক্ষণাবেক্ষণের সাথে রেখেছিল around
মাইকেল বি

37

স্পষ্টভাবে একটি ইন্টারফেস বাস্তবায়ন করার জন্য কিছু অতিরিক্ত কারণ:

পিছনে সামঞ্জস্যতা : ICloneableইন্টারফেস পরিবর্তনের ক্ষেত্রে , প্রয়োগকারী পদ্ধতি শ্রেণীর সদস্যদের তাদের পদ্ধতি স্বাক্ষর পরিবর্তন করতে হবে না।

ক্লিনার কোড : Cloneপদ্ধতিটি আইক্লোনেবল থেকে অপসারণ করা হলে একটি সংকলক ত্রুটি থাকবে, তবে আপনি যদি পদ্ধতিটি স্পষ্টভাবে প্রয়োগ করেন তবে অব্যক্ত 'অনাথ' পাবলিক পদ্ধতিতে শেষ করতে পারেন

দৃ strongটাইপিং : সুপারকার্টের একটি উদাহরণ উদাহরণ সহকারে বর্ণনা করার জন্য, এটি আমার পছন্দসই নমুনা কোড হবে, আপনি যখন উদাহরণস্বরূপ সদস্য হিসাবে সরাসরি ডাকেন তখন ICloneableস্পষ্টভাবে প্রয়োগ করা দৃ Clone()strongly়ভাবে টাইপ করার অনুমতি দেয় MyObject:

public class MyObject : ICloneable
{
  public MyObject Clone()
  {
    // my cloning logic;  
  }

  object ICloneable.Clone()
  {
    return this.Clone();
  }
}

তার জন্য, আমি পছন্দ করতাম interface ICloneable<out T> { T Clone(); T self {get;} }। লক্ষ্য করুন যে ICloneable<T>টি-তে ইচ্ছাকৃত কোনও বাধা নেই, যদিও কোনও বস্তু সাধারণত কেবল তার ভিত্তি হতে পারে তবে নিরাপদে ক্লোন করা যায় তবে যে কোনও শ্রেণীর অবজেক্টকে নিরাপদে ক্লোন করা যায় এমন কোনও বেস ক্লাস থেকে উদ্ভব করতে পারে। এটির জন্য অনুমতি দেওয়ার জন্য, আমি উত্তরাধিকারসূত্রে ক্লাস করার জন্য একটি পাবলিক ক্লোন পদ্ধতি প্রকাশের বিরুদ্ধে সুপারিশ করব। পরিবর্তে protectedক্লোনিং পদ্ধতি এবং সিল করা ক্লাস সহ উত্তরাধিকারসূত্রে ক্লাস রয়েছে যা সেগুলি থেকে প্রাপ্ত এবং পাবলিক ক্লোনিং প্রকাশ করে।
সুপারক্যাট

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

সমস্ত 3 টি উদাহরণ অসম্ভব পরিস্থিতি এবং ব্রেক ইন্টারফেসের সেরা অনুশীলনের উপর নির্ভর করে।
মিকিডি

13

আর একটি দরকারী কৌশল হ'ল কোনও ফাংশনের জনসাধারণের প্রয়োগের একটি পদ্ধতিতে এমন একটি মান ফেরত দেওয়া যা কোনও ইন্টারফেসে নির্দিষ্ট চেয়ে নির্দিষ্ট।

উদাহরণস্বরূপ, কোনও অবজেক্ট বাস্তবায়ন করতে পারে ICloneableতবে এর সর্বজনীনভাবে দৃশ্যমানClone পদ্ধতিটি তার নিজস্ব প্রকারটি ফেরত দিতে পারে।

তেমনি, একটি পদ্ধতি এমন IAutomobileFactoryএকটি Manufactureপদ্ধতি থাকতে পারে যা একটি ফেরত দেয় Automobile, তবে ক FordExplorerFactory, যা প্রয়োগ করে IAutomobileFactory, তার Manufactureপদ্ধতিটি একটি FordExplorer(যা থেকে প্রাপ্ত Automobile) ফিরে আসতে পারে । কোড যা জানে যে এটিতে কোনও টাইপকাস্ট না করে ফিরিয়ে দেওয়া কোনও বস্তুর উপর একটি নির্দিষ্ট বৈশিষ্ট্য FordExplorerFactoryব্যবহার করা যেতে পারে , যখন কোডটি কেবলমাত্র জানত যে এটির কোনও প্রকারেরটি কেবল এটি হিসাবে তার প্রত্যাবর্তনকে মোকাবেলা করবে ।FordExplorerFordExplorerFactoryIAutomobileFactoryAutomobile


2
+1 ... এটি আমার স্পষ্ট ইন্টারফেস বাস্তবায়নের পছন্দসই ব্যবহার হবে, যদিও একটি ছোট কোডের নমুনা সম্ভবত এই গল্পটির চেয়ে কিছুটা বেশি স্পষ্ট হবে :)
উইবে তিজসম

7

একই সদস্যের নাম এবং স্বাক্ষরের সাথে আপনার দুটি ইন্টারফেস থাকলে এটি কার্যকর হয় তবে এটি কীভাবে ব্যবহৃত হয় তার উপর নির্ভর করে এর আচরণ পরিবর্তন করতে চাই। (আমি এই জাতীয় কোড লেখার প্রস্তাব দিই না):

interface Cat
{
    string Name {get;}
}

interface Dog
{
    string Name{get;}
}

public class Animal : Cat, Dog
{
    string Cat.Name
    {
        get
        {
            return "Cat";
        }
    }

    string Dog.Name
    {
        get
        {
            return "Dog";
        }
    }
}
static void Main(string[] args)
{
    Animal animal = new Animal();
    Cat cat = animal; //Note the use of the same instance of Animal. All we are doing is picking which interface implementation we want to use.
    Dog dog = animal;
    Console.WriteLine(cat.Name); //Prints Cat
    Console.WriteLine(dog.Name); //Prints Dog
}

60
সবচেয়ে অদ্ভুত OO সম্পর্কিত উদাহরণ আমি কখনও দেখেছি:public class Animal : Cat, Dog
এমবিএক্স

38
@ এমএমএক্স: যদি প্রাণীও তোতা প্রয়োগ করে, তবে এটি পলি-মরফিং প্রাণী হবে।
রেনিপেট

3
আমার মনে আছে একটি কার্টুন চরিত্র যা এক প্রান্তে একটি বিড়াল এবং অন্য প্রান্তে একটি কুকুর ;-)
জর্জ বীরবিলিস

2
৮০ এর দশকে একটি টিভি সিরিজ ছিল .. "মণিমাল" .. যেখানে কোনও মানুষ একটি
রূপে কাটাতে

মোরকিজ কিন্ডা দেখতে বিড়ালের মতো, এবং নিনজা-বিড়ালের মতোও।
সমিস

6

এটি কোনও ইন্টারফেসকে স্পষ্টভাবে প্রয়োগ করতে পাবলিক ইন্টারফেস ক্লিনার রাখতে পারে, অর্থাত আপনার Fileক্লাসটি IDisposableস্পষ্টভাবে প্রয়োগ করতে পারে এবং এমন একটি পাবলিক পদ্ধতি প্রদান Close()করতে পারে যা কোনও গ্রাহকের চেয়ে বেশি বোঝায় Dispose(

F # কেবল স্পষ্টত ইন্টারফেস প্রয়োগের প্রস্তাব দেয় যাতে আপনার কার্যকারিতা অ্যাক্সেস করার জন্য আপনাকে সর্বদা নির্দিষ্ট ইন্টারফেসে কাস্ট করতে হয়, যা ইন্টারফেসটির খুব স্পষ্ট (কোনও পাং উদ্দেশ্যে নয়) ব্যবহার করে।


আমি মনে করি VB- র বেশিরভাগ সংস্করণগুলি কেবল স্পষ্টভাবে ইন্টারফেস সংজ্ঞা সমর্থন করে।
গাবে

1
@ গ্যাবে - এটি ভিবি-র তুলনায় আরও সূক্ষ্ম - কোনও ইন্টারফেস প্রয়োগকারী সদস্যদের নামকরণ এবং অ্যাক্সেসযোগ্যতা এগুলি ইঙ্গিত দেয় যে তারা বাস্তবায়নের অংশ। সুতরাং ভিবিতে, এবং @ আইনের উত্তর (বর্তমান শীর্ষ উত্তর) সন্ধানের জন্য, আপনি যথাক্রমে জনসাধারণের সদস্য "GoFast" এবং "GoSlow" এর সাথে IDoItFast এবং IDoItSlow প্রয়োগ করতে পারেন।
দামিয়েন_ও_বিশ্বাসীরা

2
আমি আপনার নির্দিষ্ট উদাহরণটি পছন্দ করি না (আইএমএইচও, কেবলমাত্র এমন জিনিসগুলি যা লুকানো উচিত Disposeসেগুলি যা কখনও পরিষ্কারের প্রয়োজন হবে না); এর চেয়ে উত্তম উদাহরণ হ'ল অপরিবর্তনীয় সংগ্রহের বাস্তবায়নের মতো কিছু IList<T>.Add
সুপারক্যাট

5

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


ঠিক আছে, এটি ব্যাখ্যা করে যে প্রকল্পটি কেন অন্তর্নিহিত বাস্তবায়নের সাথে সংকলন করবে না।
পাওলোয়া

4

সুস্পষ্ট বাস্তবায়নের আরেকটি কারণ রক্ষণাবেক্ষণযোগ্যতা

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

সুতরাং এটি কোডের "পঠনযোগ্যতা" উন্নত করে।


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

1

একটি ভিন্ন উদাহরণ দেওয়া হয় System.Collections.Immutable , এতে লেখকরা সংগ্রহের ধরণের জন্য একটি পরিচিত API সংরক্ষণের জন্য কৌশলটি ব্যবহার করার পছন্দ করেছেন যখন ইন্টারফেসের অংশগুলি তাদের নতুন ধরণের জন্য কোনও অর্থ রাখে না।

Concretely, ImmutableList<T>কার্যকরী IList<T>এবং এইভাবে ICollection<T>( অনুক্রমে করার অনুমতি ImmutableList<T>এখনো, উত্তরাধিকার কোড সহ আরও সহজে ব্যবহার করা হবে) void ICollection<T>.Add(T item)একটি জন্য কোন জ্ঞান করে তোলে ImmutableList<T>একটি অপরিবর্তনীয় লিস্টে একটি উপাদান যোগ বিদ্যমান তালিকায় পরিবর্তন করা উচিত নয়, যেহেতু: ImmutableList<T>এছাড়াও আহরিত থেকে IImmutableList<T>যার IImmutableList<T> Add(T item)ব্যবহার করা যেতে পারে অপরিবর্তনীয় তালিকা

সুতরাং, ক্ষেত্রে নিম্নলিখিত হিসাবে শেষ পর্যন্ত Addবাস্তবায়নগুলি ImmutableList<T>:

public ImmutableList<T> Add(T item)
{
    // Create a new list with the added item
}

IImmutableList<T> IImmutableList<T>.Add(T value) => this.Add(value);

void ICollection<T>.Add(T item) => throw new NotSupportedException();

int IList.Add(object value) => throw new NotSupportedException();

0

সুস্পষ্টভাবে সংজ্ঞায়িত ইন্টারফেসের ক্ষেত্রে, সমস্ত পদ্ধতি স্বয়ংক্রিয়ভাবে ব্যক্তিগত হয়, আপনি এগুলিতে অ্যাক্সেস মডিফায়ারটিকে সর্বজনীন দিতে পারবেন না। ধরুন:

interface Iphone{

   void Money();

}

interface Ipen{

   void Price();
}


class Demo : Iphone, Ipen{

  void Iphone.Money(){    //it is private you can't give public               

      Console.WriteLine("You have no money");
  }

  void Ipen.Price(){    //it is private you can't give public

      Console.WriteLine("You have to paid 3$");
  }

}


// So you have to cast to call the method


    class Program
    {
        static void Main(string[] args)
        {
            Demo d = new Demo();

            Iphone i1 = (Iphone)d;

            i1.Money();

            ((Ipen)i1).Price();

            Console.ReadKey();
        }
    }

  // You can't call methods by direct class object

1
"সমস্ত পদ্ধতি স্বয়ংক্রিয়ভাবে ব্যক্তিগত" - এটি প্রযুক্তিগতভাবে সঠিক নয়, খ / সি যদি তারা প্রকৃতপক্ষে ব্যক্তিগত হয় তবে তারা কল করার যোগ্য হবে না, ingালাই বা নাও।
সমিস

0

আমরা এভাবেই স্পষ্টত ইন্টারফেস তৈরি করতে পারি: আমাদের যদি দুটি ইন্টারফেস থাকে এবং উভয় ইন্টারফেসের একই পদ্ধতি থাকে এবং একটি একক শ্রেণীর এই 2 টি ইন্টারফেসের উত্তরাধিকারী হয় তাই যখন আমরা একটি ইন্টারফেস পদ্ধতি বলি তখন কম্পাইলারটি কোন পদ্ধতিটি কল করতে হবে তা বিভ্রান্ত হয়ে যায়, তাই আমরা পারি সুস্পষ্ট ইন্টারফেস ব্যবহার করে এই সমস্যাটি পরিচালনা করুন। আমি নীচে দেওয়া একটি উদাহরণ এখানে।

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace oops3
{
    interface I5
    {
        void getdata();    
    }
    interface I6
    {
        void getdata();    
    }

    class MyClass:I5,I6
    {
        void I5.getdata()
        {
           Console.WriteLine("I5 getdata called");
        }
        void I6.getdata()
        {
            Console.WriteLine("I6 getdata called");
        }
        static void Main(string[] args)
        {
            MyClass obj = new MyClass();
            ((I5)obj).getdata();                     

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