সি # এক্সটেনশন পদ্ধতির সমান জাভা


176

আমি এক্সটেনশন পদ্ধতিটি ব্যবহার করে সি # তে যেমন বস্তুর তালিকায় একটি কার্যকারিতা বাস্তবায়ন করতে দেখছি।

এটার মতো কিছু:

List<DataObject> list;
// ... List initialization.
list.getData(id);

আমি জাভাতে এটি কীভাবে করব?


8
এটি দেখুন: github.com/nicholas22/jpropel, উদাহরণস্বরূপ: নতুন স্ট্রিং [] {"জেমস", "জন", "জন", "এডি" where। কোথাও (প্রারম্ভের সাথে ("জে")) আলাদা ( এটি লম্বোক-পিজি ব্যবহার করে যা এক্সটেনশান পদ্ধতির সদর্থকতা সরবরাহ করে।
NT_

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

3
যেমন java.lang.String একটি চূড়ান্ত শ্রেণি, তাই আপনি এটি প্রসারিত করতে পারবেন না। স্ট্যাটিক পদ্ধতি ব্যবহার করা একটি উপায় তবে এটি কোডটি অপঠনযোগ্য কখনও কখনও দেখায় I আমি মনে করি সি # কম্পিউটার ল্যাং হিসাবে একটি বয়স রেখে গেছে। সম্প্রসারণের পদ্ধতি, আংশিক ক্লাস, লাইনকিউ এবং আরও কিছু ..
দাভুত গার্বিজ

7
@ রোডরননার, রোফেল! অনুপস্থিত ভাষার বৈশিষ্ট্যটির সর্বোত্তম প্রতিবেদনটি হ'ল ভাষা অনুপস্থিত বৈশিষ্ট্যটি অশুভ এবং অবাঞ্ছিত। এটি জানা যায়।
কर्क ভোল

6
সম্প্রসারণের পদ্ধতিগুলি "দুষ্ট" নয়। তারা কোড পঠনযোগ্যতার ব্যাপক উন্নতি করে। জাভাতে অনেকগুলি দুর্বল নকশার সিদ্ধান্তের মধ্যে আরও একটি।
csauve

উত্তর:


196

জাভা এক্সটেনশন পদ্ধতি সমর্থন করে না।

পরিবর্তে, আপনি একটি নিয়মিত স্ট্যাটিক পদ্ধতি তৈরি করতে পারেন, বা আপনার নিজের ক্লাস লিখতে পারেন।


63
এক্সটেনশন পদ্ধতিগুলি ব্যবহার করার পরে আমি নষ্ট হয়েছি - তবে স্থির পদ্ধতিগুলিও কৌশলটি করবে।
বিবিকিচিকেনরোবট

31
তবে বাক্য গঠনটি খুব সুন্দর, এবং প্রোগ্রামটি বোঝার সহজ করে তোলে :) আমি এটিও পছন্দ করি যে রুবি আপনাকে প্রায় একই জিনিস করার অনুমতি দেয়, আপনি বাস্তবে অন্তর্নির্মিত ক্লাসগুলিকে সংশোধন করতে এবং নতুন পদ্ধতি যুক্ত করতে পারেন।
জ্ঞাতসিল্যা

18
@ কেন: হ্যাঁ, এবং এটিই পুরো বিষয়টি! আপনি জাভাতে এবং কেন সরাসরি জেভিএম বাইট কোডে লেখেন না? এটি কি শুধু সিনট্যাক্সের বিষয় নয়?
ফায়োডর সোইকিন

30
এক্সটেনশন পদ্ধতিগুলি অন্য কোনও শ্রেণীর অতিরিক্ত স্ট্যাটিক পদ্ধতির তুলনায় কোডকে অনেক বেশি মার্জিত করে তুলতে পারে। প্রায় সমস্ত আধুনিক ভাষাগুলি কোনও ধরণের বিদ্যমান শ্রেণি সম্প্রসারণের অনুমতি দেয়: সি #, পিএইচপি, উদ্দেশ্য-সি, জাভাস্ক্রিপ্ট। জাভা অবশ্যই এখানে তার বয়স দেখায়। কল্পনা করুন আপনি JSONObject ডিস্কে লিখতে চান। আপনি কি jsonobj.writeToDisk () বা someunrelatedclass.writeToDisk (jsonobj) কল করেন?
ভোগ্য

8
জাভা ঘৃণা করার কারণ বাড়ছে। এবং আমি কয়েক বছর আগে তাদের সন্ধান বন্ধ করে দিয়েছি ......
জন ডেমেট্রিউ

54

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

এবং আমি মনে করি না জাভাতে জেনেরিকের পরামিতিগুলির ধরণের ক্ষয়ের শব্দার্থক কারণে এটি জাভাতে প্রয়োগ করা সম্ভব is


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

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

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

1
@ user1686250 জাভাতে প্রয়োগ করা সম্ভব ("জাভা দ্বারা" আমি ধরে নিয়েছি যে আপনি বাইকোড বলতে বোঝাচ্ছেন যা একটি জেভিএম দিয়ে চলেছে) ... কোটলিন, যা বাইটকোডে সংকলিত এক্সটেনশন রয়েছে। স্থির পদ্ধতিগুলির তুলনায় এটি কেবল সিনট্যাকটিক চিনি। সমতুল্য জাভা দেখতে কেমন তা দেখতে আপনি ইন্টেলিজে ডিকম্পিলারটি ব্যবহার করতে পারেন।
জেফ্রি ব্লাটম্যান

@ user1686250 আপনি জেনেরিকগুলি সম্পর্কে কী লিখছেন তা বিকাশ করতে পারেন (বা একটি লিঙ্ক দিন) কারণ জেনেরিক সম্পর্কে আমি একেবারেই পয়েন্ট পাই না। সাধারণ স্ট্যাটিক পদ্ধতি ছাড়া অন্য কোন উপায়ে এটি সম্পর্কিত?
সি.চ্যাম্পাগেন

17

প্রজেক্ট লম্বোক একটি টীকা সরবরাহ করে @ExtensionMethodযা আপনি যে কার্যকারিতা জিজ্ঞাসা করছেন তা অর্জন করতে ব্যবহার করা যেতে পারে।


3
ম্যানিফো ल्ड জাভা জন্য বিস্তৃত, বিরামবিহীন সি #-স্টাইল এক্সটেনশন পদ্ধতি সমর্থন সরবরাহ করে , আপনি যেমন ক্লাসগুলিতে নিয়ন্ত্রণ করেন না এমন পদ্ধতিতে পদ্ধতি যুক্ত করার অনুমতি দেয় ,। বিক্ষোভ: http://manifold.systems/images/ExistanceMethod.mp4java.lang.String
স্কট

10

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

package extensions.java.lang.String;

import manifold.ext.api.*;

@Extension
public class MyStringExtension {

  public static void print(@This String thiz) {
    System.out.println(thiz);
  }

  @Extension
  public static String lineSeparator() {
    return System.lineSeparator();
  }
}

7

এক্সটেন্ড ভাষা - যা জাভার একটি সুপার সেট, এবং জাভা উত্স কোড 1 তে সংকলিত  - এটি সমর্থন করে।


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

@ বম্বোকা যেমন অন্যেরা লিখেছেন, জাভাতে এক্সটেনশন পদ্ধতি নেই। সুতরাং জাভাতে সংকলিত এক্সটেন্ড কোডটি কোনওভাবে জাভা এক্সটেনশন পদ্ধতি তৈরি করে না। তবে আপনি যদি এক্সটেন্ডে একচেটিয়াভাবে কাজ করেন তবে আপনি খেয়াল করবেন না বা যত্ন করবেন না। তবে, আপনার প্রশ্নের উত্তর দেওয়ার জন্য আপনার অচলভাবে কোনও স্ট্যাটিক পদ্ধতি নেই। XTend প্রধান লেখক এই সম্পর্কে একটি ব্লগ এন্ট্রি হয়েছে blog.efftinge.de/2011/11/...
এরিক জি Hagstrom

হ্যাঁ, জানি না কেন আমিও তা ভাবিনি। ধন্যবাদ!
ফ্যাবিও মিলহিরো

@ স্যাম আমাকে এক্সটেন্ডের সাথে পরিচয় করিয়ে দেওয়ার জন্য ধন্যবাদ - আমি এটির আগে কখনও শুনিনি।
jpaugh

7

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

অতিরিক্তভাবে, ইন্টেলিজি ম্যানিফোল্ড প্লাগইনটির মাধ্যমে ম্যানিফোল্ডের জন্য ব্যাপক সমর্থন সরবরাহ করে

ম্যানিফোল্ড গিথুব এ উপলব্ধ একটি ওপেন সোর্স প্রকল্প ।



5

জাভাতে এ জাতীয় বৈশিষ্ট্য নেই। পরিবর্তে আপনি হয় আপনার তালিকা প্রয়োগের নিয়মিত সাবক্লাস তৈরি করতে পারেন বা বেনামে অভ্যন্তর শ্রেণি তৈরি করতে পারেন:

List<String> list = new ArrayList<String>() {
   public String getData() {
       return ""; // add your implementation here. 
   }
};

সমস্যাটি এই পদ্ধতিটি কল করা। আপনি এটি "জায়গায়" করতে পারেন:

new ArrayList<String>() {
   public String getData() {
       return ""; // add your implementation here. 
   }
}.getData();

112
এটি একেবারে অকেজো।
স্ল্যাक्स

2
@ স্লাকস: ঠিক কেন? এটি নিজের দ্বারা প্রস্তাবিত "আপনার নিজের শ্রেণি লিখুন"।
গোরান জোভিক

23
@ গোরান: এগুলি আপনাকে একটি পদ্ধতির সংজ্ঞা দেয়, তারপরে তাড়াতাড়ি একবার ফোন করুন
স্লাকস

3
@ স্ল্যাকস: ঠিক আছে, পয়েন্ট নেওয়া হয়েছে। সেই সীমাবদ্ধ সমাধানের সাথে তুলনা করে একটি নামী শ্রেণি লেখা ভাল হবে be
গোরান জোভিক

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

4

মনে হচ্ছে কিছু ছোট সুযোগ যে ডিফেন্ডার পদ্ধতি (অর্থাত ডিফল্ট পদ্ধতি) জাভা 8. তবে সেটিকে করা হতে পারে, যতটা আমি তাদের বোঝেনা, সবাই শুধু অনুমতি মত লেখক একটি এরinterface ব্যাপকভাবে এটি প্রসারিত, না নির্বিচারে ব্যবহারকারীদের।

ডিফেন্ডার পদ্ধতিগুলি + ইন্টারফেস ইঞ্জেকশনটি তখন সি #-স্টাইল এক্সটেনশন পদ্ধতিগুলিকে সম্পূর্ণরূপে প্রয়োগ করতে সক্ষম হবে, তবে এএএএফআইএসস, ইন্টারফেস ইঞ্জেকশনটি এখনও জাভা 8 রোড-ম্যাপে নেই।


3

এই প্রশ্নে পার্টিতে দেরি করে ফেলুন তবে কারও পক্ষে এটি দরকারী মনে হলে আমি কেবল একটি সাবক্লাস তৈরি করেছি:

public class ArrayList2<T> extends ArrayList<T> 
{
    private static final long serialVersionUID = 1L;

    public T getLast()
    {
        if (this.isEmpty())
        {
            return null;
        }
        else
        {       
            return this.get(this.size() - 1);
        }
    }
}

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

1
এটি কেবল এটি @ এমবিএক্স নয়। সিল নন-সিল করা ক্লাসগুলির শ্রেণীর কার্যকারিতা বাড়ানোর জন্যও এক্সটেনশন পদ্ধতিগুলি দরকারী তবে যা আপনি প্রসারিত করতে পারবেন না কারণ যেগুলি ফিরে আসার উদাহরণগুলি আপনি নিয়ন্ত্রণ করেন না, যেমন: HTTPContextBase যা একটি বিমূর্ত শ্রেণি।
ফ্যাবিও মিলিহিরো

@ ফ্যাবিওমিলিহিরো আমি উদারভাবে অ্যাবস্ট্রাক্ট ক্লাসগুলিকে সেই প্রসঙ্গে "ইন্টারফেস" হিসাবে অন্তর্ভুক্ত করেছি। অটো উত্পাদিত ক্লাস (xsd.exe) একই ধরণের: উত্পন্ন ফাইলগুলি সংশোধন করে আপনি তাদের প্রসারিত করতে পারবেন না। আপনি সাধারণত "আংশিক" ব্যবহার করে তাদের প্রসারিত করবেন যার জন্য তাদের একই সমাবেশে থাকতে হবে। যদি তা না হয় তবে এক্সটেনশন পদ্ধতিগুলি দেখতে বেশ সুন্দর বিকল্প। শেষ পর্যন্ত, এগুলি কেবল স্থির পদ্ধতি (আপনি উত্পন্ন আইএল কোডটি দেখলে কোনও পার্থক্য নেই)।
এমবিএক্স

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

2

জাভা ৮-এর পরে উপলব্ধ ডিফল্ট পদ্ধতি প্রয়োগের মাধ্যমে আমরা জাভাতে সি # এক্সটেনশন পদ্ধতির প্রয়োগের অনুকরণ করতে পারি We আমরা একটি ইন্টারফেসটি সংজ্ঞায়িত করে শুরু করি যা আমাদের বেস () পদ্ধতির মাধ্যমে সাপোর্ট অবজেক্টে অ্যাক্সেসের অনুমতি দেবে:

public interface Extension<T> {

    default T base() {
        return null;
    }
}

ইন্টারফেসের রাষ্ট্র থাকতে পারে না বলে আমরা নালাগুলি ফিরে আসি তবে এটি প্রক্সি দিয়ে পরে ঠিক করতে হবে।

এক্সটেনশনের বিকাশকারীকে এক্সটেনশন পদ্ধতিযুক্ত একটি নতুন ইন্টারফেস দ্বারা এই ইন্টারফেসটি প্রসারিত করতে হবে। ধরা যাক আমরা তালিকা ইন্টারফেসে প্রতিটি গ্রাহককে যুক্ত করতে চাই:

public interface ListExtension<T> extends Extension<List<T>> {

    default void foreach(Consumer<T> consumer) {
        for (T item : base()) {
            consumer.accept(item);
        }
    }

}

যেহেতু আমরা এক্সটেনশন ইন্টারফেসটি প্রসারিত করি, আমরা আমাদের সংযুক্ত সমর্থন আইটেমটি অ্যাক্সেস করতে আমাদের এক্সটেনশন পদ্ধতির অভ্যন্তরে বেস () পদ্ধতিটি কল করতে পারি।

এক্সটেনশন ইন্টারফেসটির অবশ্যই একটি ফ্যাক্টরি পদ্ধতি থাকতে হবে যা প্রদত্ত সহায়তা সামগ্রীর এক্সটেনশন তৈরি করবে:

public interface Extension<T> {

    ...

    static <E extends Extension<T>, T> E create(Class<E> type, T instance) {
        if (type.isInterface()) {
            ExtensionHandler<T> handler = new ExtensionHandler<T>(instance);
            List<Class<?>> interfaces = new ArrayList<Class<?>>();
            interfaces.add(type);
            Class<?> baseType = type.getSuperclass();
            while (baseType != null && baseType.isInterface()) {
                interfaces.add(baseType);
                baseType = baseType.getSuperclass();
            }
            Object proxy = Proxy.newProxyInstance(
                    Extension.class.getClassLoader(),
                    interfaces.toArray(new Class<?>[interfaces.size()]),
                    handler);
            return type.cast(proxy);
        } else {
            return null;
        }
    }
}

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

public class ExtensionHandler<T> implements InvocationHandler {

    private T instance;

    private ExtensionHandler(T instance) {
        this.instance = instance;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if ("base".equals(method.getName())
                && method.getParameterCount() == 0) {
            return instance;
        } else {
            Class<?> type = method.getDeclaringClass();
            MethodHandles.Lookup lookup = MethodHandles.lookup()
                .in(type);
            Field allowedModesField = lookup.getClass().getDeclaredField("allowedModes");
            makeFieldModifiable(allowedModesField);
            allowedModesField.set(lookup, -1);
            return lookup
                .unreflectSpecial(method, type)
                .bindTo(proxy)
                .invokeWithArguments(args);
        }
    }

    private static void makeFieldModifiable(Field field) throws Exception {
        field.setAccessible(true);
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField
                .setInt(field, field.getModifiers() & ~Modifier.FINAL);
    }

}

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

public class Program {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("a", "b", "c");
        ListExtension<String> listExtension = Extension.create(ListExtension.class, list);
        listExtension.foreach(System.out::println);
    }

}

সুতরাং, এটি এমন একটি উপায় যা আমরা জাভাতে নতুন চুক্তি যুক্ত করে তাদের প্রসারিত করার ক্ষমতা অনুকরণ করতে পারি যা আমাদের প্রদত্ত বস্তুগুলিতে অতিরিক্ত পদ্ধতি কল করার অনুমতি দেয়।

নীচে আপনি এক্সটেনশন ইন্টারফেসের কোডটি পেতে পারেন:

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

public interface Extension<T> {

    public class ExtensionHandler<T> implements InvocationHandler {

        private T instance;

        private ExtensionHandler(T instance) {
            this.instance = instance;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            if ("base".equals(method.getName())
                    && method.getParameterCount() == 0) {
                return instance;
            } else {
                Class<?> type = method.getDeclaringClass();
                MethodHandles.Lookup lookup = MethodHandles.lookup()
                    .in(type);
                Field allowedModesField = lookup.getClass().getDeclaredField("allowedModes");
                makeFieldModifiable(allowedModesField);
                allowedModesField.set(lookup, -1);
                return lookup
                    .unreflectSpecial(method, type)
                    .bindTo(proxy)
                    .invokeWithArguments(args);
            }
        }

        private static void makeFieldModifiable(Field field) throws Exception {
            field.setAccessible(true);
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        }

    }

    default T base() {
        return null;
    }

    static <E extends Extension<T>, T> E create(Class<E> type, T instance) {
        if (type.isInterface()) {
            ExtensionHandler<T> handler = new ExtensionHandler<T>(instance);
            List<Class<?>> interfaces = new ArrayList<Class<?>>();
            interfaces.add(type);
            Class<?> baseType = type.getSuperclass();
            while (baseType != null && baseType.isInterface()) {
                interfaces.add(baseType);
                baseType = baseType.getSuperclass();
            }
            Object proxy = Proxy.newProxyInstance(
                    Extension.class.getClassLoader(),
                    interfaces.toArray(new Class<?>[interfaces.size()]),
                    handler);
            return type.cast(proxy);
        } else {
            return null;
        }
    }

}

1
এটাই এক নোংরামি!
দিমিত্রি অ্যাভটনোমভ

1

একটি সাজসজ্জার বস্তু ভিত্তিক নকশা প্যাটার্ন ব্যবহার করা যেতে পারে । জাভাটির স্ট্যান্ডার্ড লাইব্রেরিতে এই প্যাটার্নটির ব্যবহারের উদাহরণ হ'ল ডেটাআউটপুট স্ট্রিম

একটি তালিকার কার্যকারিতা বৃদ্ধির জন্য এখানে কিছু কোড রয়েছে:

public class ListDecorator<E> implements List<E>
{
    public final List<E> wrapee;

    public ListDecorator(List<E> wrapee)
    {
        this.wrapee = wrapee;
    }

    // implementation of all the list's methods here...

    public <R> ListDecorator<R> map(Transform<E,R> transformer)
    {
        ArrayList<R> result = new ArrayList<R>(size());
        for (E element : this)
        {
            R transformed = transformer.transform(element);
            result.add(transformed);
        }
        return new ListDecorator<R>(result);
    }
}

PS আমি একটি বড় ফ্যান Kotlin । এটিতে এক্সটেনশন পদ্ধতি রয়েছে এবং এটি জেভিএম-তেও চালায়।


0

আপনি কালেকশন ইন্টারফেসটি প্রয়োগ করে এবং জাভা সংগ্রহের জন্য উদাহরণ যোগ করে (আরই) এর মাধ্যমে এক্সটেনশন / সহায়ক পদ্ধতি তৈরি করতে পারেন:

public class RockCollection<T extends Comparable<T>> implements Collection<T> {
private Collection<T> _list = new ArrayList<T>();

//###########Custom extension methods###########

public T doSomething() {
    //do some stuff
    return _list  
}

//proper examples
public T find(Predicate<T> predicate) {
    return _list.stream()
            .filter(predicate)
            .findFirst()
            .get();
}

public List<T> findAll(Predicate<T> predicate) {
    return _list.stream()
            .filter(predicate)
            .collect(Collectors.<T>toList());
}

public String join(String joiner) {
    StringBuilder aggregate = new StringBuilder("");
    _list.forEach( item ->
        aggregate.append(item.toString() + joiner)
    );
    return aggregate.toString().substring(0, aggregate.length() - 1);
}

public List<T> reverse() {
    List<T> listToReverse = (List<T>)_list;
    Collections.reverse(listToReverse);
    return listToReverse;
}

public List<T> sort(Comparator<T> sortComparer) {
    List<T> listToReverse = (List<T>)_list;
    Collections.sort(listToReverse, sortComparer);
    return listToReverse;
}

public int sum() {
    List<T> list = (List<T>)_list;
    int total = 0;
    for (T aList : list) {
        total += Integer.parseInt(aList.toString());
    }
    return total;
}

public List<T> minus(RockCollection<T> listToMinus) {
    List<T> list = (List<T>)_list;
    int total = 0;
    listToMinus.forEach(list::remove);
    return list;
}

public Double average() {
    List<T> list = (List<T>)_list;
    Double total = 0.0;
    for (T aList : list) {
        total += Double.parseDouble(aList.toString());
    }
    return total / list.size();
}

public T first() {
    return _list.stream().findFirst().get();
            //.collect(Collectors.<T>toList());
}
public T last() {
    List<T> list = (List<T>)_list;
    return list.get(_list.size() - 1);
}
//##############################################
//Re-implement existing methods
@Override
public int size() {
    return _list.size();
}

@Override
public boolean isEmpty() {
    return _list == null || _list.size() == 0;
}

-7

Java8 এখন ডিফল্ট পদ্ধতিগুলি সমর্থন করে যা C#এর এক্সটেনশন পদ্ধতির অনুরূপ ।


9
ভুল; এই প্রশ্নের উদাহরণ এখনও অসম্ভব।
এসএলএক্স

@ এসএলাক্স জাভা এবং সি # এক্সটেনশনের মধ্যে পার্থক্য কী?
ফ্যাবিও মিলিহিরো

3
ডিফল্ট পদ্ধতিগুলি কেবল ইন্টারফেসের মধ্যেই সংজ্ঞায়িত করা যায়। docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
স্ল্যাक्स

দারওয়ার, এই মন্তব্য থ্রেডটি শুধুমাত্র যেখানে ছিল ডিফল্ট পদ্ধতিগুলি উল্লেখ করা হয়েছিল, যা আমি মরিয়া হয়ে মনে করার চেষ্টা করছিলাম। নাম উল্লেখ না করে তাদের উল্লেখ করার জন্য ধন্যবাদ! :-) (লিঙ্কটির জন্য ধন্যবাদ @
এসএলক্স

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