জাভা: সাব-প্যাকেজের দৃশ্যমানতা?


150

আমার প্রকল্পে আমার দুটি প্যাকেজ রয়েছে: odp.projএবং odp.proj.test। কিছু নির্দিষ্ট পদ্ধতি রয়েছে যা আমি এই দুটি প্যাকেজটিতে কেবল ক্লাসে দৃশ্যমান হতে চাই। কিভাবে আমি এটি করতে পারব?

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




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

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

উত্তর:


165

আপনি পারবেন না। জাভা একটি উপপ্যাকেজের কোন ধারণা নেই, তাই odp.projএবং odp.proj.testসম্পূর্ণরূপে পৃথক প্যাকেজ আছে।


10
যদিও আমি এটি পছন্দ করি তবে এটি বিভ্রান্তিকর যে বেশিরভাগ আইডিই একই নামের প্যাকেজগুলি একসাথে রাখে। বিবৃতির জন্য ধন্যবাদ.
জ্যাকসঅনএফ 1 এর

এটি কঠোরভাবে সঠিক নয়: জেএলএস উপ- প্যাকেজগুলি সংজ্ঞায়িত করে, যদিও তাদের কাছে একমাত্র ভাষার তাত্পর্য হ'ল "শীর্ষ স্তরের ধরণের মতো একই সাধারণ নামযুক্ত একটি প্যাকেজটির বিরুদ্ধে" নিষিদ্ধ করা। আমি এই প্রশ্নের বিস্তারিতভাবে ব্যাখ্যা করে এই প্রশ্নের একটি উত্তর যুক্ত করেছি।
এম জাস্টিন

59

আপনার প্যাকেজগুলির নামগুলি ইঙ্গিত দেয় যে এখানে অ্যাপ্লিকেশনটি ইউনিট পরীক্ষার জন্য। ব্যবহৃত সাধারণ প্যাটার্নটি হ'ল আপনি পরীক্ষা করতে চান এমন ক্লাস এবং ইউনিট টেস্ট কোড একই প্যাকেজে (আপনার ক্ষেত্রে odp.proj) তবে বিভিন্ন উত্স গাছের মধ্যে রাখুন। সুতরাং আপনি আপনার ক্লাসগুলি src/odp/projএবং আপনার পরীক্ষার কোডটি প্রবেশ করান test/odp/proj

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


11

এই মধ্যে কোন বিশেষ সম্পর্ক নেই odp.projএবং odp.proj.test- তারা শুধু নামে হিসেবে দৃশ্যত সম্পর্কিত ঘটে।

যদি odp.proj.test প্যাকেজটি কেবল পরীক্ষার ব্যবস্থা করে থাকে তবে আপনি একই প্যাকেজের নাম ( odp.proj) ব্যবহার করতে পারেন । ইক্লিপস এবং নেটবিনের মতো আইডিই একই প্যাকেজের নামের সাথে তবে ইউনাইট শব্দার্থবিদ্যার সাহায্যে পৃথক ফোল্ডার ( src/main/java/odp/projএবং src/test/java/odp/proj) তৈরি করবে ।

নোট করুন যে এই আইডিইগুলি পদ্ধতিগুলির জন্য পরীক্ষাগুলি উত্পন্ন করে odp.projএবং এটি বিদ্যমান না এমন পরীক্ষার পদ্ধতিগুলির জন্য উপযুক্ত ফোল্ডার তৈরি করবে।


5

আমি যখন ইন্টেলিজজে এটি করি তখন আমার উত্স গাছটি দেখতে দেখতে এমন লাগে:

src         // source root
- odp
   - proj   // .java source here
- test      // test root
  - odp
     - proj // JUnit or TestNG source here

4

সম্পাদনা: জাভাতে যদি সাবপ্যাকেজের ধারণা না থাকে তবে এটিকে ঘিরে কোনও উপায় আছে কি? আমার কাছে এমন কয়েকটি পদ্ধতি রয়েছে যা আমি কেবল পরীক্ষকগণ এবং সেই প্যাকেজের অন্যান্য সদস্যদের জন্যই উপলব্ধ হতে চাই।

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

ইউনিট পরীক্ষার জন্য, এবং যদি অনেকগুলি পুনরায় লেখা না করে এটি সম্ভব হয় তবে একই প্যাকেজটি ব্যবহার করার জন্য পরামর্শগুলি অনুসরণ করুন।


3

অন্যরা যেমন ব্যাখ্যা করেছেন, জাভাতে "সাবপ্যাকেজ" বলে কোনও জিনিস নেই: সমস্ত প্যাকেজগুলি বিচ্ছিন্ন এবং তাদের পিতামাতার কাছ থেকে কিছুই পায় না।

অন্য প্যাকেজ থেকে সুরক্ষিত শ্রেণীর সদস্যদের অ্যাক্সেসের একটি সহজ উপায় হ'ল শ্রেণিকে প্রসারিত করা এবং সদস্যদের ওভাররাইড করা।

উদাহরণস্বরূপ, ClassInAপ্যাকেজে অ্যাক্সেস করতে a.b:

package a;

public class ClassInA{
    private final String data;

    public ClassInA(String data){ this.data = data; }

    public String getData(){ return data; }

    protected byte[] getDataAsBytes(){ return data.getBytes(); }

    protected char[] getDataAsChars(){ return data.toCharArray(); }
}

সেই প্যাকেজে এমন একটি শ্রেণী তৈরি করুন যা আপনার প্রয়োজনীয় পদ্ধতিগুলিকে ওভাররাইড করে ClassInA:

package a.b;

import a.ClassInA;

public class ClassInAInB extends ClassInA{
    ClassInAInB(String data){ super(data); }

    @Override
    protected byte[] getDataAsBytes(){ return super.getDataAsBytes(); }
}

এটি আপনাকে অন্যান্য প্যাকেজে ক্লাসের জায়গায় ওভাররাইডিং ক্লাসটি ব্যবহার করতে দেয়:

package a.b;

import java.util.Arrays;

import a.ClassInA;

public class Driver{
    public static void main(String[] args){
        ClassInA classInA = new ClassInA("string");
        System.out.println(classInA.getData());
        // Will fail: getDataAsBytes() has protected access in a.ClassInA
        System.out.println(Arrays.toString(classInA.getDataAsBytes()));

        ClassInAInB classInAInB = new ClassInAInB("string");
        System.out.println(classInAInB.getData());
        // Works: getDataAsBytes() is now accessible
        System.out.println(Arrays.toString(classInAInB.getDataAsBytes()));
    }
}

নোট করুন যে এটি কেবল সুরক্ষিত সদস্যদের জন্যই কাজ করে যা ক্লাসগুলি (উত্তরাধিকার) প্রসারিত এবং প্যাকেজ-ব্যক্তিগত সদস্যদের জন্য নয় যা কেবল একই প্যাকেজের মধ্যে উপ / প্রসারিত শ্রেণীর জন্য দৃশ্যমান। আশা করি এটি কাউকে সাহায্য করবে!


3

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

জাভা 13 জেএলএস :

প্যাকেজের সদস্যরা হ'ল এর উপ-প্যাকেজগুলি এবং প্যাকেজের সমস্ত সংকলন ইউনিটে ঘোষণা করা সমস্ত শীর্ষ স্তরের শ্রেণি এবং শীর্ষ স্তরের ইন্টারফেস প্রকারগুলি।

উদাহরণস্বরূপ, জাভা এসই প্ল্যাটফর্ম এপিআইতে:

  • প্যাকেজ javasubpackages হয়েছে awt, applet, io, lang, net, এবং util, কিন্তু কোন সংকলন ইউনিট।
  • প্যাকেজের java.awtএকটি সাব- প্যাকেজ নাম রয়েছে image, পাশাপাশি ক্লাস এবং ইন্টারফেসের ধরণের ঘোষণাসহ কয়েকটি সংকলন ইউনিট রয়েছে।

প্যাকেজ এবং ক্লাস / ইন্টারফেসের মধ্যে নামকরণের সীমাবদ্ধতাগুলি যেমন প্রযোজ্য তেমনি সাব-প্যাকেজ ধারণাটি প্রাসঙ্গিক:

একটি প্যাকেজটিতে একই নামের দুটি সদস্য বা একটি সংকলন-সময় ত্রুটির ফলাফল থাকতে পারে।

এখানে কিছু উদাহরন:

  • যেহেতু প্যাকেজটির java.awtএকটি সাবপ্যাকেজ রয়েছে image, এটিতে কোনও শ্রেণি বা ইন্টারফেসের নাম ঘোষণা করা থাকতে পারে (এবং না) image
  • যদি সেই প্যাকেজে নামের কোনও প্যাকেজ mouseএবং কোনও সদস্যের টাইপ Buttonথাকে (যা তখন বলা যেতে পারে mouse.Button), তবে পুরোপুরি যোগ্যতাসম্পন্ন নাম mouse.Buttonবা কোনও প্যাকেজ থাকতে পারে না mouse.Button.Click
  • যদি com.nighthacks.java.jagকোনও প্রকারের পুরোপুরি যোগ্যতাসম্পন্ন নাম হয় তবে এমন কোনও প্যাকেজ থাকতে পারে না যার পুরোপুরি যোগ্যতাসম্পন্ন নাম হয় হয় com.nighthacks.java.jagবা হয় com.nighthacks.java.jag.scrabble

যাইহোক, এই নামকরণের সীমাবদ্ধতা ভাষা দ্বারা উপ-প্যাকেজগুলিতে একমাত্র তাত্পর্যপূর্ণ:

প্যাকেজগুলির জন্য শ্রেণিবিন্যাসের নামকরণ কাঠামোটি প্রচলিত পদ্ধতিতে সম্পর্কিত প্যাকেজগুলি সংগঠিত করার জন্য সুবিধাজনক বলে মনে করা হয়, তবে সেই প্যাকেজটিতে শীর্ষ স্তরের প্রকার হিসাবে একই সরল নাম সহ একটি প্যাকেজযুক্ত প্যাকেজের বিরুদ্ধে নিষেধাজ্ঞার বাইরে অন্য কোনও তাত্পর্য নেই has ।

উদাহরণস্বরূপ, সেখানে নামে একটি প্যাকেজ মধ্যে কোন বিশেষ অ্যাক্সেস সম্পর্ক নেই oliverএবং অন্য প্যাকেজ নামে oliver.twist, বা নামে প্যাকেজ মধ্যে evelyn.woodএবং evelyn.waugh। অর্থাত্, প্যাকেজের নামযুক্ত কোডের অন্য কোনও প্যাকেজের কোডের চেয়ে oliver.twistপ্যাকেজের মধ্যে ঘোষিত ধরণেরগুলিতে এর oliverচেয়ে ভাল অ্যাক্সেস নেই ।


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

হয় পদ্ধতিটি সর্বজনীন করা যেতে পারে এবং সমস্ত প্যাকেজ (সহ odp.projএবং odp.proj.test) প্রদত্ত পদ্ধতিগুলি অ্যাক্সেস করতে সক্ষম হবে, বা পদ্ধতিটি প্যাকেজটিকে ব্যক্তিগত (ডিফল্ট দৃশ্যমানতা) তৈরি করা যেতে পারে, এবং সরাসরি কোড অ্যাক্সেস করার জন্য প্রয়োজনীয় সমস্ত কোড অবশ্যই এতে রেখে দিতে হবে পদ্ধতি হিসাবে একই (উপ) প্যাকেজ।

এটি বলেছিল, জাভাতে খুব মানক অনুশীলন হ'ল উত্স কোড হিসাবে একই প্যাকেজে টেস্ট কোডটি রাখা, তবে ফাইল সিস্টেমে ভিন্ন স্থানে। উদাহরণস্বরূপ, মধ্যে ম্যাভেন বিল্ড টুল, কনভেনশন এই উৎস এবং পরীক্ষা ফাইল করা হবে src/main/java/odp/projএবং src/test/java/odp/projযথাক্রমে। বিল্ড টুলটি যখন এটি সংকলন করে, ফাইলের দুটি সেট odp.projপ্যাকেজে শেষ হয় , তবে কেবলমাত্র srcফাইলগুলি উত্পাদন শিল্পে অন্তর্ভুক্ত থাকে; পরীক্ষার ফাইলগুলি কেবলমাত্র নির্মাণের ফাইলগুলি যাচাই করতে বিল্ড টাইমে ব্যবহৃত হয়। এই সেটআপের মাধ্যমে, পরীক্ষার কোডটি যে প্যাকেজটিকে এটি পরীক্ষা করছে তার ব্যক্তিগত বা সুরক্ষিত কোড অবাধে অ্যাক্সেস করতে পারে, কারণ তারা একই প্যাকেজে থাকবে।

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


0

পদ্ধতির সামনে অ্যাক্সেস মডিফায়ার না রেখে আপনি বলবেন যে এটি প্যাকেজটি ব্যক্তিগত।
নিম্নলিখিত উদাহরণটি দেখুন।

package odp.proj;
public class A
{
    void launchA() { }
}

package odp.proj.test;
public class B
{
    void launchB() { }
}

public class Test
{
    public void test()
    {
        A a = new A();
        a.launchA()    // cannot call launchA because it is not visible
    }
}

0

প্যাকেজভিজিবলহেলপার ক্লাসের সাহায্যে এবং এটি প্যাকেজভিজিবলহেলফ্যাক্টরি হিমায়িত করার আগে ব্যক্তিগত রাখার জন্য, আমরা যে কোনও জায়গায় লঞ্চএ (প্যাকেজভিজিবলহেলপার দ্বারা) পদ্ধতিতে আবেদন করতে পারি :)

package odp.proj;
public class A
 {
    void launchA() { }
}

public class PackageVisibleHelper {

    private final PackageVisibleHelperFactory factory;

    public PackageVisibleHelper(PackageVisibleHelperFactory factory) {
        super();
        this.factory = factory;
    }

    public void launchA(A a) {
        if (factory == PackageVisibleHelperFactory.INSTNACNE && !factory.isSampleHelper(this)) {
            throw new IllegalAccessError("wrong PackageVisibleHelper ");
        }
        a.launchA();
    }
}


public class PackageVisibleHelperFactory {

    public static final PackageVisibleHelperFactory INSTNACNE = new PackageVisibleHelperFactory();

    private static final PackageVisibleHelper HELPER = new PackageVisibleHelper(INSTNACNE);

    private PackageVisibleHelperFactory() {
        super();
    }

    private boolean frozened;

    public PackageVisibleHelper getHelperBeforeFrozen() {
        if (frozened) {
            throw new IllegalAccessError("please invoke before frozen!");
        }
        return HELPER;
    }

    public void frozen() {
        frozened = true;
    }

    public boolean isSampleHelper(PackageVisibleHelper helper) {
        return HELPER.equals(helper);
    }
}
package odp.proj.test;

import odp.proj.A;
import odp.proj.PackageVisibleHelper;
import odp.proj.PackageVisibleHelperFactory;

public class Test {

    public static void main(String[] args) {

        final PackageVisibleHelper helper = PackageVisibleHelperFactory.INSTNACNE.getHelperBeforeFrozen();
        PackageVisibleHelperFactory.INSTNACNE.frozen();


        A a = new A();
        helper.launchA(a);

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