ইন্টারফেসে কনস্ট্রাক্টর?


148

আমি জানি ইন্টারফেসে কনস্ট্রাক্টর সংজ্ঞা দেওয়া সম্ভব নয় possible তবে আমি ভাবছি কেন, কারণ আমি মনে করি এটি খুব কার্যকর হতে পারে।

সুতরাং আপনি নিশ্চিত হতে পারেন যে কোনও শ্রেণীর কিছু ক্ষেত্র এই ইন্টারফেসের প্রতিটি বাস্তবায়নের জন্য সংজ্ঞায়িত।

উদাহরণস্বরূপ নিম্নলিখিত বার্তা শ্রেণীর বিবেচনা করুন:

public class MyMessage {

   public MyMessage(String receiver) {
      this.receiver = receiver;
   }

   private String receiver;

   public void send() {
      //some implementation for sending the mssage to the receiver
   }
}

যদি এই শ্রেণীর জন্য একটি ইন্টারফেস সংজ্ঞায়িত করা হয় যাতে আমার আরও ক্লাস থাকতে পারে যা মেসেজ ইন্টারফেসটি বাস্তবায়িত করে, আমি কেবল প্রেরণ পদ্ধতিটি নির্ধারণ করতে পারি না কনস্ট্রাক্টরকে। সুতরাং আমি কীভাবে নিশ্চিত করতে পারি যে এই শ্রেণীর প্রতিটি প্রয়োগের সত্যই একটি রিসিভার সেট রয়েছে? আমি যদি কোনও পদ্ধতি ব্যবহার করি তবে আমি setReceiver(String receiver)নিশ্চিত হতে পারি না যে এই পদ্ধতিটি আসলেই বলা হয়েছিল। কনস্ট্রাক্টরে আমি এটি নিশ্চিত করতে পারতাম।



2
আপনি বলছেন "কন্সট্রাক্টরে আমি নিশ্চিত করতে পারি [এই শ্রেণীর প্রতিটি প্রয়োগের সত্যই একটি রিসিভার সেট রয়েছে]"। তবে না, আপনি সম্ভবত এটি করতে পারেন নি। এই ধরণের কনস্ট্রাক্টরকে সংজ্ঞায়িত করা সম্ভব হয় তবে প্যারামিটারটি কেবল আপনার বাস্তবায়নকারীদের কাছেই শক্তিশালী ইঙ্গিত হতে পারে - তবে তারা চাইলে কেবল এটিকে এড়িয়ে যাওয়া বেছে নিতে পারে।
জুলিয়েন সিলান্দ

3
@ ম্যাটটিব উম্ম, এটি আলাদা ভাষা।
ইয়েসনেস

উত্তর:


129

আপনি বর্ণিত কিছু জিনিস গ্রহণ:

"সুতরাং আপনি নিশ্চিত হতে পারেন যে কোনও শ্রেণীর কিছু ক্ষেত্র এই ইন্টারফেসের প্রতিটি প্রয়োগের জন্য সংজ্ঞায়িত করা হয়েছে।"

"যদি এই শ্রেণীর জন্য একটি ইন্টারফেস সংজ্ঞায়িত করা হয় যাতে আমার আরও ক্লাস থাকতে পারে যা মেসেজ ইন্টারফেসটি বাস্তবায়িত করে, আমি কেবল প্রেরণ পদ্ধতিটি নির্ধারণ করতে পারি না কনস্ট্রাক্টরকে"

... এই প্রয়োজনীয়তাগুলি ঠিক বিমূর্ত ক্লাসগুলির জন্য exactly


তবে নোট করুন যে @Sebi বর্ণিত ব্যবহারের মামলাটি (আমার পিতামাতার নির্মাতাদের কাছ থেকে ওভারলোড হওয়া পদ্ধতিগুলি কল করা) আমার উত্তরে বর্ণিত একটি খারাপ ধারণা।
আরএসপি

44
ম্যাট, এটি স্পষ্টভাবে সত্য, তবে বিমূর্ত শ্রেণিগুলি একক-উত্তরাধিকারের সীমাবদ্ধতায় ভোগে, যা লোকক্রমকে নির্দিষ্ট করার অন্যান্য উপায়গুলির দিকে নজর দেয়।
সিপারকিন্স

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

7
@ সিগার্কিনস এটি সত্য হলেও, আমি প্রস্তাব দিচ্ছি না যে কেবল একটি বিমূর্ত শ্রেণি ব্যবহার করলে সেবীর ব্যবহারের বিষয়টি সমাধান হবে। যদি কিছু হয় তবে একটি Messageইন্টারফেস ঘোষণা করা ভাল যা send()পদ্ধতিটি সংজ্ঞায়িত করে , এবং সেবি যদি Messageইন্টারফেসটি বাস্তবায়নের জন্য একটি "বেস" শ্রেণি সরবরাহ করতে চায় তবে তার AbstractMessageপাশাপাশি একটি সরবরাহও করুন। অ্যাবস্ট্রাক্ট ক্লাসগুলি ইন্টারফেসের স্থান গ্রহণ করা উচিত নয়, এটি প্রস্তাব দেওয়ার চেষ্টা করা হয়নি।
ম্যাট বি

2
বুঝেছি, ম্যাট। আমি আপনার সাথে তর্ক করছিলাম না, আরও ইঙ্গিত করে যে অপটি যা চায় এটির জন্য এটি সম্পূর্ণ প্রতিস্থাপন নয় ।
সিপারকিনস

76

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

অথবা কোডে:

interface Named { Named(String name); }
interface HasList { HasList(List list); }

class A implements Named, HasList {

  /** implements Named constructor.
   * This constructor should not be used from outside, 
   * because List parameter is missing
   */
  public A(String name)  { 
    ...
  }

  /** implements HasList constructor.
   * This constructor should not be used from outside, 
   * because String parameter is missing
   */
  public A(List list) {
    ...
  }

  /** This is the constructor that we would actually 
   * need to satisfy both interfaces at the same time
   */ 
  public A(String name, List list) {
    this(name);
    // the next line is illegal; you can only call one other super constructor
    this(list); 
  }
}

1
ভাষা এই জাতীয় জিনিসগুলিকে অনুমতি দিয়ে এটি করতে পারে নিclass A implements Named, HashList { A(){HashList(new list()); Named("name");} }
মাকো

1
"ইন্টারফেসে কনস্ট্রাক্টর" এর সবচেয়ে দরকারী অর্থ, যদি অনুমতি দেওয়া হয়, তবে যদি new Set<Fnord>()"আমার হিসাবে ব্যবহার করতে পারি এমন কিছু আমাকে দিন" অর্থ এই অর্থ ব্যাখ্যা করা যায় Set<Fnord>; লেখক যদি সেই জিনিসগুলির জন্য যান যা বাস্তবায়নের Set<T>উদ্দেশ্যে HashSet<T>যা অন্য কোনও কিছুর জন্য বিশেষ প্রয়োজন হয় না, তবে ইন্টারফেসটি সংজ্ঞায়িত new Set<Fnord>()করতে পারে এর সমার্থক হিসাবে বিবেচিত হতে পারে new HashSet<Fnord>()। কোনও শ্রেণীর একাধিক ইন্টারফেস বাস্তবায়নের জন্য কোনও সমস্যা হতে পারে না, যেহেতু new InterfaceName()কেবল ইন্টারফেস দ্বারা মনোনীত একটি শ্রেণি তৈরি করা হবে ।
সুপারক্যাট

পাল্টা-যুক্তি: আপনার A(String,List)কন্সট্রাকটর মনোনীত কন্সট্রাকটর হতে পারে, এবং A(String)এবং A(List)মাধ্যমিক বেশী যে সেটিতে কল হতে পারে। আপনার কোড একটি পাল্টা উদাহরণ নয়, কেবল একটি দরিদ্র।
বেন লেগিগেরো

আপনি কোনও বাস্তবায়নে সমস্ত কনস্ট্রাক্টরকে কল করবেন কেন ?! হ্যাঁ, যদি এটি কর্টারের সাথে আরও ইন্টারফেস প্রয়োগ করে, একটি স্ট্রিং সহ একটি এবং একটি ইনট সহ একটি, এটির জন্য দুটি সিটার দরকার - তবে হয় বা ব্যবহার করা যেতে পারে। যদি তা প্রযোজ্য না হয় তবে ক্লাস কেবল উভয়ই ইন্টারফেস প্রয়োগ করে না। তাতে কি!? (যদিও ইন্টারফেসে ctor না থাকার অন্যান্য কারণ রয়েছে)।
কাই

@ কাই না, কোনও উদাহরণ তৈরি করার সময় এটি উভয় ইন্টারফেস কনস্ট্রাক্টরকে কল করতে হবে। অন্য কথায়: আমার উদাহরণে, উদাহরণটির একটি নাম এবং তালিকা উভয়ই রয়েছে, সুতরাং প্রতিটি উদাহরণের নাম এবং তালিকা উভয়ই ইনস্ট্যান্ট করা দরকার।
ড্যানিয়েল কুলম্যান

13

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

আপনি যে ব্যবহারের বর্ণনাটি বর্ণনা করেছেন এটি একটি বিমূর্ত শ্রেণীর অনুরূপ যেখানে নির্মাতা একটি বিমূর্ত পদ্ধতিটির একটি পদ্ধতি কল করে যা একটি শিশু শ্রেণিতে প্রয়োগ করা হয়।

এখানে সহজাত সমস্যাটি হ'ল বেস কন্সট্রাক্টর মৃত্যুদন্ড কার্যকর করার সময়, শিশু অবজেক্টটি এখনও নির্মিত হয়নি, এবং অপ্রত্যাশিত অবস্থায় থ্রফরফ।

সংক্ষিপ্তসার হিসাবে: আপনি যখন অভিভাবকগণের কাছ থেকে ওভারলোড হওয়া পদ্ধতিগুলি মাইন্ডপ্রডকে উদ্ধৃত করার জন্য কল করছেন তখন কি সমস্যাটি জিজ্ঞাসা করছে :

সাধারণভাবে আপনাকে অবশ্যই কোনও কনস্ট্রাক্টরে কোনও চূড়ান্ত পদ্ধতি কল করা এড়াতে হবে। সমস্যাটি হ'ল দৃষ্টিকোণ ক্লাসে ইনিশিয়াল ইনিশিয়ালিসার / ভেরিয়েবল ইনিশিয়েশন বেস ক্লাসের কনস্ট্রাক্টরের পরে সঞ্চালিত হয়


6

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

যাইহোক এই workaround আপনি getInstance()এই ইন্টারফেসের সমস্ত অবজেক্ট ইনস্ট্যান্ট করতে প্রয়োজন ।

যেমন

public interface Module {
    Module getInstance(Receiver receiver);
}

5

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

দ্বিতীয় কারণ-সাবক্লাসের অবজেক্ট তৈরির সময়, প্যারেন্ট কনস্ট্রাক্টরকে ডাকা হয়। তবে যদি একাধিক ইন্টারফেস প্রয়োগ করা হয় তবে ইন্টারফেস কনস্ট্রাক্টরের কল করার সময় একটি দ্বন্দ্ব দেখা দেয় যে ইন্টারফেসের কনস্ট্রাক্টর প্রথমে কল করবে


3

আপনি যদি নিশ্চিত করতে চান যে প্রতিটি ইন্টারফেসের প্রয়োগের ক্ষেত্রে নির্দিষ্ট ক্ষেত্র রয়েছে, তবে আপনাকে কেবল আপনার ইন্টারফেসে সেই ক্ষেত্রের জন্য প্রাপ্তি যুক্ত করতে হবে :

interface IMyMessage(){
    @NonNull String getReceiver();
}
  • এটি encapsulation ভাঙবে না
  • এটি আপনার ইন্টারফেসটি ব্যবহারকারী প্রত্যেককে জানতে দেবে যে Receiverকোনওভাবে ক্লাসে অবজেক্টটি পাস করতে হবে (হয় কনস্ট্রাক্টর দ্বারা বা সেটার দ্বারা)

2

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


1

কেন (মন্তব্য থেকে নেওয়া) জন্য এই প্রশ্নটি দেখুন ।

আপনার যদি সত্যিই এটির মতো কিছু করার দরকার হয় তবে আপনি ইন্টারফেসের চেয়ে একটি বিমূর্ত বেস ক্লাসটি পেতে পারেন।


1

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


0

এই প্রযুক্তি ব্যবহার করে একটি উদাহরণ এখানে। এই সুনির্দিষ্ট উদাহরণে কোডটি ফায়ারবেসে একটি মক ব্যবহার করে একটি কল করছে MyCompletionListenerযা একটি বিমূর্ত শ্রেণি হিসাবে একটি মুখোশযুক্ত একটি ইন্টারফেস, একটি নির্মাণকারীর সাথে একটি ইন্টারফেস

private interface Listener {
    void onComplete(databaseError, databaseReference);
}

public abstract class MyCompletionListener implements Listener{
    String id;
    String name;
    public MyCompletionListener(String id, String name) {
        this.id = id;
        this.name = name;
    }
}

private void removeUserPresenceOnCurrentItem() {
    mFirebase.removeValue(child("some_key"), new MyCompletionListener(UUID.randomUUID().toString(), "removeUserPresenceOnCurrentItem") {
        @Override
        public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {

        }
    });
    }
}

@Override
public void removeValue(DatabaseReference ref, final MyCompletionListener var1) {
    CompletionListener cListener = new CompletionListener() {
                @Override
                public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                    if (var1 != null){
                        System.out.println("Im back and my id is: " var1.is + " and my name is: " var1.name);
                        var1.onComplete(databaseError, databaseReference);
                    }
                }
            };
    ref.removeValue(cListener);
}

আপনি কিভাবে privateঅ্যাক্সেস মডিফায়ার ব্যবহার করতে পারেন interface?
রুদ্র

0

সাধারণত কনস্ট্রাক্টররা নির্দিষ্ট শ্রেণীর অ-স্থিতিশীল সদস্যকে বস্তুর প্রতি শ্রদ্ধা জানানোর জন্য izing

ইন্টারফেসের জন্য কোনও অবজেক্ট সৃষ্টি নেই কারণ কেবল ঘোষিত পদ্ধতি রয়েছে তবে সংজ্ঞায়িত পদ্ধতি নেই। আমরা ঘোষিত পদ্ধতিগুলিতে কেন বস্তু তৈরি করতে পারি না তা হ'ল-অবজেক্ট ক্রিয়েশন অ স্থিতিশীল সদস্যদের জন্য কিছু মেমরি (হিপ মেমরিতে) বরাদ্দ করা ছাড়া কিছুই নয়।

জেভিএম সদস্যদের জন্য মেমরি তৈরি করবে যা পুরোপুরি বিকাশযুক্ত এবং ব্যবহারের জন্য প্রস্তুত। এই সদস্যদের উপর ভিত্তি করে, জেভিএম তাদের জন্য কতটা মেমরির প্রয়োজন তা গণনা করে এবং স্মৃতি তৈরি করে।

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

উপসংহার:

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

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