জাভা মার্কার ইন্টারফেস?


134

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

তবে ইদানীং আমি জেনেছি যে এটির সংকলক বা জেভিএমের সাথে আসলে কোনও সম্পর্ক নেই। উদাহরণস্বরূপ, ক্ষেত্রে Serializableইন্টারফেস পদ্ধতি writeObject(Object)এর ObjectOutputStreamভালো কিছু করে instanceOf Serializableকিনা তা সনাক্ত করতে বর্গ কার্যকরী Serializable& ছোঁড়ার NotSerializableExceptionনেই। কোডটিতে সমস্ত কিছু পরিচালনা করা হয় এবং এটি একটি নকশা-প্যাটার্ন বলে মনে হয় তাই আমি মনে করি আমরা আমাদের নিজস্ব চিহ্নিতকারী ইন্টারফেসগুলি সংজ্ঞায়িত করতে পারি।

এখন আমার সন্দেহ:

  1. 1 ম পয়েন্টে উপরে বর্ণিত মার্কার ইন্টারফেসের সংজ্ঞাটি কি ভুল? তখন আমরা কীভাবে একটি মার্কার ইন্টারফেসটি সংজ্ঞায়িত করতে পারি?

  2. এবং instanceOfঅপারেটরটি ব্যবহার না করে কেন পদ্ধতিটি এমন কিছু হতে পারে না writeObject(Serializable)যাতে রানটাইমের চেয়ে কমপাইল টাইম টাইপ চেকিং থাকে?

  3. মার্কার ইন্টারফেসের চেয়ে টিকা কীভাবে ভাল?


8
Serializableযেমন একটি টিকা হ'ল বাজে কথা এবং @NonNullইন্টারফেস হিসাবে আজেবাজে। আমি বলব: টীকাগুলি হ'ল চিহ্নিতকারী + মেটাডেটা। বিটিডাব্লু: টীকাগুলির ফোরফুনার ছিলেন এক্সডোকলেট, জাভাদোকে জন্মগ্রহণ করেছিলেন, এনটেশনগুলির দ্বারা নিহত হয়েছিল।
গ্রিম

উত্তর:


117
  1. 1 ম পয়েন্টে উপরে বর্ণিত মার্কার ইন্টারফেসের সংজ্ঞাটি কি ভুল? - অংশগুলির মধ্যে এটি সঠিক যে (1) একটি চিহ্নিতকারী ইন্টারফেস অবশ্যই ফাঁকা থাকতে হবে, এবং (2) এটি বাস্তবায়ন করাকে বোঝানো হচ্ছে বাস্তবায়নকারী শ্রেণীর কিছু বিশেষ চিকিত্সা বোঝানো। যে অংশটি ভুল তা হ'ল এটি বোঝায় যে জেভিএম বা সংকলক এই শ্রেণীর অবজেক্টগুলিকে অন্যরকম আচরণ করবে: আপনি জাভা বর্গ লাইব্রেরির কোড যা এই বিষয়গুলিকে ক্লোনযোগ্য, সিরিয়ালাইজযোগ্য ইত্যাদি হিসাবে বিবেচনা করে তা পর্যবেক্ষণে আপনি সঠিক বলেছেন It সংকলক বা জেভিএম এর সাথে কিছুই করার নেই।
  2. উদাহরণস্বরূপ অপারেটরটি ব্যবহারের পরিবর্তে পদ্ধতিটি এমন কিছু হতে পারে না writeObject(Serializable)যাতে একটি সংকলন-টাইপ ধরণের চেক থাকে - এটি আপনাকে যখন "প্লেইন Object" প্রয়োজন হয় তখন চিহ্নিত কোডার ইন্টারফেসের নাম সহ আপনার কোডকে দূষিত করা এড়াতে দেয় । উদাহরণস্বরূপ, আপনি যদি এমন একটি ক্লাস তৈরি করেন যা সিরিয়ালাইজযোগ্য হতে হবে এবং এতে অবজেক্ট সদস্য রয়েছে তবে আপনাকে কাস্টিং করতে বাধ্য করা হবে বা Serializableসংকলনের সময় আপনার অবজেক্টগুলি তৈরি করতে হবে । এটি অসুবিধাজনক, কারণ ইন্টারফেসটি কোনও কার্যকারিতা থেকে বঞ্চিত।
  3. মার্কার ইন্টারফেসের চেয়ে টিকা কীভাবে ভাল? - তারা আপনাকে ক্লাস সম্পর্কে আলাদা আলাদা প্রকার তৈরি না করে ক্লাস সম্পর্কে মেটাডেটা পৌঁছে দেওয়ার একই উদ্দেশ্য অর্জন করতে দেয়। এনটেশনগুলি আরও শক্তিশালী, প্রোগ্রামাররা ক্লাসগুলিতে এটি "গ্রাস" করে এমন আরও পরিশীলিত তথ্যের পাস দিয়ে দেয়।

14
আমি যেভাবে সর্বদা এটি বুঝতে পারি তা হ'ল টীকাগুলি এক ধরণের 'মার্কার ইন্টারফেস ২.০': জাভা ১.১ থেকে সিরিয়ালাইজিবল বিদ্যমান, টীকাগুলি 1.5 সালে যোগ করা হয়েছিল
ব্লেগ

এবং writeObjectব্যক্তিগত কারণ , এর অর্থ হল যে কোনও শ্রেণীর সুপারক্লাস বাস্তবায়ন কল করতে হবে না
র‌্যাচেট ফ্রিক

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

ঠিক আছে, Cloneableএটির ক্ষেত্রে এটি কোনও গ্রন্থাগার বা জেভিএমের চিকিত্সা যা পাল্টানো হয়েছে তা পরিষ্কার নয়।
হলগার

"[...] এর জন্য পৃথক প্রকার তৈরি না করেই।" - আমি বলব যে এগুলি হুবহু যা তাদের আলাদা করে: একটি মার্কার ইন্টারফেস একটি প্রকারের সাথে পরিচয় করিয়ে দেয় , যখন টিকা (ধরণের) না করে।
আইয়ুব

22

এটি প্রয়োগ Serializableকরা সম্ভব নয় writeObjectকারণ অ-সিরিয়ালাইজযোগ্য শ্রেণীর বাচ্চারা সিরিয়ালাইজযোগ্য হতে পারে তবে তাদের উদাহরণগুলি অভিভাবক শ্রেণিতে ফিরে যেতে পারে। ফলস্বরূপ, অ-সিরিয়ালযোগ্য কিছু (যেমন Object) এর জন্য একটি রেফারেন্স রাখা মানে এই নয় যে উল্লিখিত উদাহরণটি সত্যই সিরিয়াল করা যায় না। উদাহরণস্বরূপ

   Object x = "abc";
   if (x instanceof Serializable) {
   }

অভিভাবক শ্রেণি ( Object) সিরিয়ালযোগ্য নয় এবং এটির প্যারামিটার-কম নির্মাণকারী ব্যবহার করে সূচনা করা হবে। দ্বারা সমর্থিত মান x, String, serializable এবং কন্ডিশনাল স্টেটমেন্ট চালানো হবে।


6

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

উপরেরগুলি একটি ব্লগ পোস্টের অনুলিপি হিসাবে শুরু হয়েছিল তবে ব্যাকরণের জন্য হালকাভাবে সম্পাদনা করা হয়েছে।


6
এটি অনুলিপি করা ঠিক আছে তবে দয়া করে উত্সটিও উল্লেখ করুন: javarevisited.blogspot.com/2012/01/… । এছাড়াও আপনি খুব ভাল বানান ভুল বানান পেস্ট না করলে। :)
সৌরভ পাটিল

6

আমি 1 এবং 2 সন্দেহ সমাধানের জন্য একটি সহজ বিক্ষোভ করেছি:

আমাদের চলমান ইন্টারফেস থাকবে যা MobilePhone.javaক্লাস দ্বারা প্রয়োগ করা হবে এবং আরও একটি শ্রেণি LandlinePhone.javaযা চলনযোগ্য ইন্টারফেস বাস্তবায়ন করে না

আমাদের চিহ্নিতকারী ইন্টারফেস:

package com;

public interface Movable {

}

LandLinePhone.java এবং MobilePhone.java

 package com;

 class LandLinePhone {
    // more code here
 }
 class MobilePhone implements Movable {
    // more code here
 }

আমাদের কাস্টম ব্যতিক্রম শ্রেণি: প্যাকেজ কম;

public class NotMovableException extends Exception {

private static final long serialVersionUID = 1L;

    @Override
    public String getMessage() {
        return "this object is not movable";
    }
    // more code here
    }

আমাদের পরীক্ষা ক্লাস: TestMArkerInterface.java

package com;

public class TestMarkerInterface {

public static void main(String[] args) throws NotMovableException {
    MobilePhone mobilePhone = new MobilePhone();
    LandLinePhone landLinePhone = new LandLinePhone();

    TestMarkerInterface.goTravel(mobilePhone);
    TestMarkerInterface.goTravel(landLinePhone);
}

public static void goTravel(Object o) throws NotMovableException {
    if (!(o instanceof Movable)) {
        System.out.println("you cannot use :" + o.getClass().getName() + "   while travelling");
        throw new NotMovableException();
    }

    System.out.println("you can use :" + o.getClass().getName() + "   while travelling");
}}

এখন যখন আমরা প্রধান শ্রেণি সম্পাদন করি:

you can use :com.MobilePhone while travelling
you cannot use :com.LandLinePhone while travelling
Exception in thread "main" com.NotMovableException: this object is not movable
    at com.TestMarkerInterface.goTravel(TestMarkerInterface.java:22)
    at com.TestMarkerInterface.main(TestMarkerInterface.java:14)

যা কখনও শ্রেণীর প্রয়োগকারী মার্কার ইন্টারফেস Movableপরীক্ষায় উত্তীর্ণ হবে অন্যথায় ত্রুটি বার্তা প্রদর্শিত হবে।

সিরিয়ালাইজেবল , ক্লোনাইয়েবল ইত্যাদির instanceOfজন্য এভাবে অপারেটর চেক করা হয়


5

একটি / একটি চিহ্নিতকরণ ইন্টারফেস এর নাম হিসাবে প্রস্তাবিত কেবল একটি শ্রেণি কিছু ঘোষণা করে যে সম্পর্কে জানে এমন কিছু অবহিত করার জন্য এটি বিদ্যমান । যে কোনও কিছুই Serializableইন্টারফেসের জন্য জেডিকে ক্লাস হতে পারে , বা কোনও কাস্টমের জন্য আপনার লেখা কোনও ক্লাস।

খ / যদি এটি চিহ্নিতকারী ইন্টারফেস হয় তবে এটি কোনও পদ্ধতির অস্তিত্বকে বোঝানো উচিত নয় - ইন্টারফেসে অন্তর্নিহিত পদ্ধতিটি অন্তর্ভুক্ত করা ভাল। তবে আপনি এটি ডিজাইন করার সিদ্ধান্ত নিতে পারেন হিসাবে আপনি চান আপনি যদি জানেন কেন আপনি এটি প্রয়োজন

সি / খালি ইন্টারফেস এবং একটি টীকাতে কোনও পার্থক্য নেই যা কোনও মান বা পরামিতি ব্যবহার করে না। তবে পার্থক্যটি এখানে রয়েছে: একটি টিকাটি কী / মানগুলির একটি তালিকা ঘোষণা করতে পারে যা রান সময়ে অ্যাক্সেসযোগ্য হবে।


3

ক। আমি এগুলিকে সর্বদা একটি ডিজাইনের প্যাটার্ন হিসাবে দেখেছি এবং জেভিএম-বিশেষ কিছুই আমি কিছু পরিস্থিতিতে এই প্যাটার্নটি ব্যবহার করি নি।

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

টীকাগুলি কোডে মেটা-ইনফরমেশনগুলি সরবরাহ করার লক্ষ্য এবং আমি মনে করি যে চিহ্নিতকারীটি মেটা-তথ্য। সুতরাং তারা ঠিক সেই ব্যবহারের ক্ষেত্রে।


3
  1. এটি জেভিএম এবং সংকলকগুলির সাথে (অগত্যা) কিছু করার নেই, এটির যে কোনও কোডের সাথে আগ্রহী এবং প্রদত্ত চিহ্নিতকারী ইন্টারফেসের জন্য পরীক্ষা করা হচ্ছে তার সাথে কিছু করার আছে।

  2. এটি একটি ডিজাইনের সিদ্ধান্ত এবং এটি একটি ভাল কারণে সম্পন্ন হয়েছে। অড্রিয়াস মেকাউস্কাসের উত্তর দেখুন।

  3. এই নির্দিষ্ট বিষয়ে সম্মানের সাথে, আমি এটি আরও ভাল বা খারাপ হওয়ার বিষয় মনে করি না। চিহ্নিতকারী ইন্টারফেসটি ঠিক কাজ করার কথা বলে।


আপনি কি "অড্রিয়াস মেকাসকাসের উত্তর" এর সাথে একটি লিঙ্ক যুক্ত করতে পারেন? এই পৃষ্ঠায় আমি এই নামটি দিয়ে কিছুই দেখতে পাচ্ছি না।
সারা মেসার

2

চিহ্নিতকারী ইন্টারফেসের প্রধান উদ্দেশ্য হ'ল বিশেষ ধরণের তৈরি করা যেখানে ধরণের নিজের নিজস্ব আচরণ নেই।

public interface MarkerEntity {

}

public boolean save(Object object) throws InvalidEntityFoundException {
   if(!(object instanceof MarkerEntity)) {
       throw new InvalidEntityFoundException("Invalid Entity Found, can't be  saved);
   } 
   return db.save(object);
}

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

যদিও টীকাগুলি এখন কিছু বিশেষ চিকিত্সার জন্য ক্লাস চিহ্নিত করতে ব্যবহার করতে পারে তবে মার্কার টীকাগুলি মার্কার ইন্টারফেসের জন্য নয় নামকরণের প্যাটার্নের জন্য প্রতিস্থাপন।

তবে মার্কার টীকাগুলি মার্কার ইন্টারফেসগুলি পুরোপুরি প্রতিস্থাপন করতে পারে না কারণ; মার্কার ইন্টারফেসগুলি ধরণের সংজ্ঞায়িত করতে ব্যবহৃত হয় (যেমন উপরে ইতিমধ্যে ব্যাখ্যা করা হয়েছে) যেখানে মার্কার টীকাগুলি নেই।

মার্কার ইন্টারফেস মন্তব্যের জন্য উত্স


1
এটি দেখানোর জন্য +1 যা প্রকৃতপক্ষে নিছক "সুরক্ষা" হুক হিসাবে ব্যবহৃত হয়েছিল যা কোনও প্রোগ্রামার স্পষ্টভাবে বলতে চেয়েছিলেন যে এটি ডেটাবেস উদাহরণ হিসাবে সংরক্ষণ করা যেতে পারে।
লুডভিগ ডাব্লু

1

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

চিহ্নিতকারী ইন্টারফেসগুলি সাধারণত দুটি উদ্দেশ্যে একটির জন্য ব্যবহৃত হয়:

1) অত্যধিক দীর্ঘ প্রকার এড়াতে শর্টকাট হিসাবে, যা প্রচুর জেনেরিকের সাথে ঘটতে পারে। উদাহরণস্বরূপ, বলুন আপনার কাছে এই পদ্ধতির স্বাক্ষর রয়েছে:

public void doSomething(Foobar<String, Map<String, SomethingElse<Integer, Long>>>) { ... }

এটি টাইপ করা অগোছালো এবং বিরক্তিকর, এবং আরও গুরুত্বপূর্ণ, বোঝা শক্ত। পরিবর্তে এটি বিবেচনা করুন:

public interface Widget extends Foobar<String, Map<String, SomethingElse<Integer, Long>>> { }

তারপরে আপনার পদ্ধতিটি দেখে মনে হচ্ছে:

public void doSomething(Widget widget) { ... }

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

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

public interface IterableWidget extends Iterable<String>, Widget { }

এবং আপনার কোডে:

public void doSomething(IterableWidget widget) {
    for (String s : widget) { ... }
}

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

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

0

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

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