এগুলি তাদের সাবক্লাসের এপিআইকে দূষিত করে এমন কি এমন বস্তু থাকা কি ঠিক আছে?


33

আমার একটি বেস ক্লাস আছে Base,। এটি দুটি সাবক্লাস, Sub1এবং Sub2। প্রতিটি সাবক্লাসের কিছু অতিরিক্ত পদ্ধতি রয়েছে। উদাহরণস্বরূপ, Sub1আছে Sandwich makeASandwich(Ingredients... ingredients)এবং Sub2আছে boolean contactAliens(Frequency onFrequency)

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

Baseবেশিরভাগ কার্যকারিতা সরবরাহ করে এবং আমার কাছে Baseঅনেকগুলি অবজেক্টের সংগ্রহ রয়েছে । যাইহোক, সমস্ত Baseবস্তু হয় হয় এক Sub1বা একটি Sub2, এবং কখনও কখনও আমার সেগুলি কী তাও জানতে হবে।

নিম্নলিখিতগুলি করা একটি খারাপ ধারণা বলে মনে হচ্ছে:

for (Base base : bases) {
    if (base instanceof Sub1) {
        ((Sub1) base).makeASandwich(getRandomIngredients());
        // ... etc.
    } else { // must be Sub2
        ((Sub2) base).contactAliens(getFrequency());
        // ... etc.
    }
}

সুতরাং আমি কাস্টিং ছাড়াই এড়াতে একটি কৌশল নিয়ে এসেছি। Baseএখন এই পদ্ধতিগুলি রয়েছে:

boolean isSub1();
Sub1 asSub1();
Sub2 asSub2();

এবং অবশ্যই, Sub1এই পদ্ধতিগুলি প্রয়োগ করে

boolean isSub1() { return true; }
Sub1 asSub1();   { return this; }
Sub2 asSub2();   { throw new IllegalStateException(); }

এবং Sub2তাদের বিপরীত উপায়ে প্রয়োগ করে।

দুর্ভাগ্যক্রমে, এখন Sub1এবং Sub2তাদের নিজস্ব API এ এই পদ্ধতিগুলি রয়েছে। সুতরাং আমি এটি করতে পারি, উদাহরণস্বরূপ, চালু Sub1

/** no need to use this if object is known to be Sub1 */
@Deprecated
boolean isSub1() { return true; }

/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub1 asSub1();   { return this; }

/** no need to use this if object is known to be Sub1 */
@Deprecated
Sub2 asSub2();   { throw new IllegalStateException(); }

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

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


12
সমস্ত 3 ক্লাস এখন একে অপরের সম্পর্কে জানতে হবে। সাব 3 যুক্ত করা কোডের অনেক পরিবর্তনকে জড়িত করে এবং সাব 10 যোগ করা নিখুঁতভাবে বেদনাদায়ক হবে
ড্যান পিচেলম্যান

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

1
দুঃখিত, আমি ভেবেছিলাম সহজ সরল উদাহরণ দেওয়া জিনিসগুলিকে আরও সহজ করে তুলবে। আমি কি করতে চাই তার বিস্তৃত সুযোগ সহ আমি নতুন প্রশ্ন পোস্ট করব।
কোডব্রেকার

12
আপনি কেবল ingালাইকে পুনরায় সংশোধন করছেন এবং instanceofএমনভাবে যা প্রচুর টাইপিংয়ের প্রয়োজন হয় তা ত্রুটি-প্রবণ এবং আরও সাবক্লাস যুক্ত করা শক্ত করে তোলে।
ব্যবহারকারী 253751

5
যদি Sub1এবং Sub2বিনিময়যোগ্যভাবে ব্যবহার না করা যায় তবে আপনি কেন তাদের সাথে এমন ব্যবহার করেন? আপনার 'স্যান্ডউইচ-নির্মাতারা' এবং 'এলিয়েন-কন্টাক্টেটর' আলাদাভাবে রাখবেন না কেন?
পিটার উইটভয়েট

উত্তর:


27

অন্যান্য উত্তরগুলির মতো প্রস্তাবিত হিসাবে বেস বর্গে ফাংশন যুক্ত করা বরাবরই বোধগম্য নয়। অনেকগুলি বিশেষ কেস ফাংশন যুক্ত করার সাথে অন্যথায় সম্পর্কযুক্ত উপাদানগুলিকে একসাথে বাধ্য করা হতে পারে।

উদাহরণস্বরূপ আমার একটি Animalক্লাস থাকতে পারে Catএবং এর সাথে Dogউপাদানগুলিও থাকতে পারে । যদি আমি প্রিন্ট, অথবা তাদের গুই দেখানোর জন্য সক্ষম হতে চান এটা আমার যোগ করার জন্য Overkill হতে পারে renderToGUI(...)এবং sendToPrinter(...)বেস ক্লাসে।

আপনি যে পদ্ধতিটি ব্যবহার করছেন, টাইপ-চেক এবং কাস্ট ব্যবহার করছেন তা ভঙ্গুর - তবে কমপক্ষে উদ্বেগগুলি পৃথক করে রাখে।

তবে আপনি যদি নিজেকে এই ধরণের চেক / কাস্টগুলি প্রায়শই করতে দেখেন তবে তার একটি বিকল্প হ'ল এর জন্য দর্শনার্থী / ডাবল-প্রেরণের প্যাটার্নটি প্রয়োগ করা। এটি দেখতে একরকম দেখাচ্ছে:

public abstract class Base {
  ...
  abstract void visit( BaseVisitor visitor );
}

public class Sub1 extends Base {
  ...
  void visit(BaseVisitor visitor) { visitor.onSub1(this); }
}

public class Sub2 extends Base {
  ...
  void visit(BaseVisitor visitor) { visitor.onSub2(this); }
}

public interface BaseVisitor {
   void onSub1(Sub1 that);
   void onSub2(Sub2 that);
}

এখন আপনার কোড হয়ে যায়

public class ActOnBase implements BaseVisitor {
    void onSub1(Sub1 that) {
       that.makeASandwich(getRandomIngredients())
    }

    void onSub2(Sub2 that) {
       that.contactAliens(getFrequency());
    }
}

BaseVisitor visitor = new ActOnBase();
for (Base base : bases) {
    base.visit(visitor);
}

প্রধান সুবিধাটি হ'ল যদি আপনি একটি সাবক্লাস যোগ করেন তবে আপনি নিঃশব্দে নিখোঁজ হওয়া মামলার পরিবর্তে সংকলন ত্রুটি পেয়ে যাবেন। নতুন দর্শনার্থী ক্লাসটিও ফাংশনগুলিকে টানানোর জন্য একটি দুর্দান্ত টার্গেটে পরিণত হয়। উদাহরণস্বরূপ এটি getRandomIngredients()মধ্যে সরানো অর্থ হতে পারে ActOnBase

আপনি লুপিং যুক্তিটিও বের করতে পারেন: উদাহরণস্বরূপ উপরের খণ্ডটি হয়ে উঠতে পারে

BaseVisitor.applyToArray(bases, new ActOnBase() );

আরও কিছুটা ম্যাসেজ করা এবং জাভা 8 এর ল্যাম্বডাস এবং স্ট্রিমিং ব্যবহার করা আপনাকে যেতে দেয়

bases.stream()
     .forEach( BaseVisitor.forEach(
       Sub1 that -> that.makeASandwich(getRandomIngredients()),
       Sub2 that -> that.contactAliens(getFrequency())
     ));

কোন আইএমও আপনি দেখতে পাচ্ছেন ততটাই ঝরঝরে চেহারা এবং সংযোগযুক্ত।

এখানে আরও সম্পূর্ণ জাভা 8 উদাহরণ রয়েছে:

public static abstract class Base {
    abstract void visit( BaseVisitor visitor );
}

public static class Sub1 extends Base {
    void visit(BaseVisitor visitor) { visitor.onSub1(this); }

    void makeASandwich() {
        System.out.println("making a sandwich");
    }
}

public static class Sub2 extends Base {
    void visit(BaseVisitor visitor) { visitor.onSub2(this); }

    void contactAliens() {
        System.out.println("contacting aliens");
    }
}

public interface BaseVisitor {
    void onSub1(Sub1 that);
    void onSub2(Sub2 that);

    static Consumer<Base> forEach(Consumer<Sub1> sub1, Consumer<Sub2> sub2) {

        return base -> {
            BaseVisitor baseVisitor = new BaseVisitor() {

                @Override
                public void onSub1(Sub1 that) {
                    sub1.accept(that);
                }

                @Override
                public void onSub2(Sub2 that) {
                    sub2.accept(that);
                }
            };
            base.visit(baseVisitor);
        };
    }
}

Collection<Base> bases = Arrays.asList(new Sub1(), new Sub2());

bases.stream()
     .forEach(BaseVisitor.forEach(
             Sub1::makeASandwich,
             Sub2::contactAliens));

+1: এই ধরণের জিনিসটি সাধারণত ভাষাগুলিতে ব্যবহৃত হয় যাদের সম-প্রকার এবং প্যাটার্ন মিলের জন্য প্রথম শ্রেণির সমর্থন রয়েছে এবং এটি জাভাতে একটি বৈধ নকশা, যদিও এটি সিনট্যাকটিকভাবে খুব কুৎসিত।
মানকারসে

@ মনকারসে একটি সামান্য সিনট্যাকটিক চিনি এটি কুৎসিত থেকে খুব দূরে করতে পারে - আমি এটি একটি উদাহরণ দিয়ে আপডেট করেছি।
মাইকেল অ্যান্ডারসন

অনুমান করা যাক হাইপ্যাটিকভাবে ওপি তাদের মন পরিবর্তন করে এবং একটি যুক্ত করার সিদ্ধান্ত নিয়েছে Sub3। দর্শনার্থীর মতো ঠিক একই সমস্যা নেই instanceof? এখন আপনাকে onSub3দর্শকের সাথে যুক্ত করতে হবে এবং আপনি ভুলে গেলে তা ভেঙে যায়।
রেডিওডেফ

1
@ রেডিওডেফ ভিজিটর প্যাটার্নটি সরাসরি টাইপ স্যুইচ করার মাধ্যমে ব্যবহার করার একটি সুবিধা হ'ল একবার আপনি onSub3ভিজিটর ইন্টারফেসে যোগ করার পরে আপনি নতুন ভিজিটর তৈরি করা প্রতিটি জায়গায় একটি সংকলন ত্রুটি পাবেন যা এখনও আপডেট হয়নি। বিপরীতে টাইপটি স্যুইচ করা সর্বোত্তমভাবে একটি রান-টাইম ত্রুটি তৈরি করে - যা ট্রিগার করতে আরও জটিল হতে পারে।
মাইকেল অ্যান্ডারসন

1
@ ফাইভনাইন, আপনি যদি উত্তরটির শেষের মধ্যে সেই সম্পূর্ণ উদাহরণটি যুক্ত করতে খুশি হন যা অন্যকে সহায়তা করতে পারে।
মাইকেল অ্যান্ডারসন

83

আমার দৃষ্টিকোণ থেকে: আপনার নকশাটি ভুল

প্রাকৃতিক ভাষায় অনুবাদিত, আপনি নিম্নলিখিতটি বলছেন:

আমাদের দেওয়া আছে animals, আছে catsএবং আছে fishanimalsবৈশিষ্ট্য আছে, যা সাধারণ catsএবং fish। তবে এটি যথেষ্ট নয়: কিছু বৈশিষ্ট্য রয়েছে যা catথেকে পৃথক হয় fish, সুতরাং আপনাকে সাবক্লাস করা দরকার।

এখন আপনার সমস্যা আছে যে আপনি আন্দোলনের মডেলটিকে ভুলে গেছেন । ঠিক আছে. এটি তুলনামূলকভাবে সহজ:

for(Animal a : animals){
   if (a instanceof Fish) swim();
   if (a instanceof Cat) walk();
}

তবে এটি একটি ভুল নকশা। সঠিক উপায়টি হ'ল:

for(Animal a : animals){
    animal.move()
}

যেখানে moveপ্রতিটি প্রাণীর দ্বারা ভাগ করা আচরণ আলাদাভাবে প্রয়োগ করা হবে।

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

এর অর্থ: আপনার নকশাটি ভাঙা।

আমার সুপারিশ: refactor Base, Sub1এবং Sub2


8
আপনি যদি প্রকৃত কোড সরবরাহ করেন তবে আমি সুপারিশ করতে পারি।
থমাস জাঙ্ক

9
@ কোডড্রেকার আপনি যদি সম্মত হন যে আপনার উদাহরণটি ভাল না, তবে আমি এই উত্তরটি গ্রহণ করার এবং পরে একটি নতুন প্রশ্ন লেখার পরামর্শ দিচ্ছি। কোনও আলাদা উদাহরণ থাকতে প্রশ্নটিকে পুনর্বিবেচনা করবেন না বা বিদ্যমান উত্তরগুলি বোঝায় না।
মবি ডিস্ক

16
@ কোডব্রেকার আমি মনে করি এটি আসল প্রশ্নের উত্তর দিয়ে সমস্যার "সমাধান" করে । আসল প্রশ্ন হচ্ছে: আমি কীভাবে আমার সমস্যা সমাধান করব? আপনার কোডটি সঠিকভাবে রিফ্যাক্টর করুন। Refactor যাতে আপনি .move()বা .attack()এবং সঠিকভাবে বিমূর্ত thatঅংশ - পরিবর্তে থাকার .swim(), .fly(), .slide(), .hop(), .jump(), .squirm(), .phone_home(), ইত্যাদি কিভাবে আপনি সঠিকভাবে refactor করেন? এর চেয়ে ভাল উদাহরণ ছাড়া অজানা ... তবে এখনও সাধারণত সঠিক উত্তর - উদাহরণ কোড এবং আরও বিশদ বিবরণ না দিলে।
WernerCD

11
@ কোডড্রেকার যদি আপনার শ্রেণি শ্রেণিবিন্যাস আপনাকে এইরকম পরিস্থিতিতে নিয়ে যায় তবে সংজ্ঞা দ্বারা এটি কোনও অর্থবোধ করে না
প্যাট্রিক কলিন্স

7
ক্রিসফোলের শেষ মন্তব্যে @ কোডড্রেকার সম্পর্কিত, এটি দেখার আরও একটি উপায় আছে যা সাহায্য করতে পারে। উদাহরণস্বরূপ, moveবনাম fly/ run/ ইত্যাদির সাহায্যে এটি একটি বাক্যে ব্যাখ্যা করা যেতে পারে: আপনাকে কী করতে হবে তা নয়, বস্তুটি কী করা উচিত তা বলা উচিত। অ্যাক্সেসরদের ক্ষেত্রে, আপনি এখানে যেমন মন্তব্য করেছেন তেমন আসল মামলার মতো বলে উল্লেখ করেছেন, আপনাকে অবজেক্টের প্রশ্ন জিজ্ঞাসা করা উচিত, এর অবস্থা পরীক্ষা করা উচিত নয়।
ইজকাটা

9

আপনার একদল জিনিস রয়েছে এমন পরিস্থিতিটি কল্পনা করা একটু কঠিন এবং সেগুলি স্যান্ডউইচ তৈরি করতে চান বা এলিয়েনের সাথে যোগাযোগ করতে চান। বেশিরভাগ ক্ষেত্রে যেখানে আপনি এই জাতীয় ingালাই খুঁজে পান সেখানে আপনি এক প্রকারের সাথে কাজ করবেন - যেমন ঝাঁকুনিতে আপনি ঘোষণার জন্য নোডের একটি সেট ফিল্টার করেন যেখানে getAsFunction তালিকার প্রতিটি নোডের জন্য আলাদা কিছু না করে নন-নাল ফেরায়

এটি হতে পারে যে আপনার ক্রিয়াকলাপের ক্রম সম্পাদন করা দরকার এবং ক্রিয়াটি সম্পাদনকারী অবজেক্টগুলি সম্পর্কিত যে এটি আসলে প্রাসঙ্গিক নয়।

সুতরাং তালিকার পরিবর্তে Baseকর্মের তালিকায় কাজ করুন

for (RandomAction action : actions)
   action.act(context);

কোথায়

interface RandomAction {
    void act(Context context);
} 

interface Context {
    Ingredients getRandomIngredients();
    double getFrequency();
}

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


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

1
@ কোডব্রেকার আপনার তখন অবশ্যই আপনার প্রশ্নটি পরিষ্কার করতে হবে - বেশিরভাগ সিস্টেমে তারা যা করে তা অজ্ঞেহিত একগুচ্ছ ফাংশন বলার একটি যুক্তিযুক্ত কারণ থাকতে পারে; উদাহরণস্বরূপ কোনও ইভেন্টের নিয়মগুলি প্রক্রিয়া করা বা সিমুলেশনের কোনও পদক্ষেপ সম্পাদন করা। সাধারণত এই জাতীয় সিস্টেমে একটি প্রসঙ্গ থাকে যাতে ক্রিয়াগুলি ঘটে। যদি 'getRandomIngredients' এবং 'getFre वारंवार' সম্পর্কিত না হয়, তবে একই বস্তুতে থাকা উচিত নয় এবং আপনার এখনও একটি ভিন্ন পদ্ধতির দরকার যেমন ক্রিয়াকলাপগুলি উপাদান বা ফ্রিকোয়েন্সিটির উত্স ধারণ করে।
পিট কির্খাম

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

এটি সঠিক উত্তর আইএমও। বুঝতে হবে যে Contextএকটি নতুন শ্রেণি বা এমনকি একটি ইন্টারফেস হওয়ার দরকার নেই। সাধারণত প্রসঙ্গটি কেবল কলার হয়, তাই কলগুলি ফর্মগুলিতে থাকে action.act(this)। যদি getFrequency()এবং getRandomIngredients()স্থিতিশীল পদ্ধতি হয় তবে আপনার কোনও প্রসঙ্গের দরকারও পড়তে পারে না। এইভাবে আমি বলব, একটি কাজের সারি, যা আপনার সমস্যাটি ভয়াবহর মতো মনে হচ্ছে তা বাস্তবায়ন করব would
QuestionC

এছাড়াও এটি বেশিরভাগ দর্শকের প্যাটার্ন সলিউশনের অনুরূপ। পার্থক্য আপনি ভিজিটর :: OnSub1 () / ভিজিটর :: OnSub2 () পদ্ধতি Sub1 যেমন রূপায়ণকারী করছি হয় :: অ্যাক্ট () / Sub2 :: আইন ()
QuestionC

4

কীভাবে যদি আপনার সাবক্লাসগুলি এক বা একাধিক ইন্টারফেস প্রয়োগ করে যা তারা কী করতে পারে তা নির্ধারণ করে? এটার মতো কিছু:

interface SandwichCook
{
    public void makeASandwich(String[] ingredients);
}

interface AlienRadioSignalAwarable
{
    public void contactAliens(int frequency);

}

তারপরে আপনার ক্লাসগুলি এর মতো দেখাবে:

class Sub1 extends Base implements SandwichCook
{
    public void makeASandwich(String[] ingredients)
    {
        //some code here
    }
}

class Sub2 extends Base implements AlienRadioSignalAwarable
{
    public void contactAliens(int frequency)
    {
        //some code here
    }
}

এবং আপনার জন্য লুপ হয়ে যাবে:

for (Base base : bases) {
    if (base instanceof SandwichCook) {
        base.makeASandwich(getRandomIngredients());
    } else if (base instanceof AlienRadioSignalAwarable) {
        base.contactAliens(getFrequency());
    }
}

এই পদ্ধতির দুটি প্রধান সুবিধা:

  • জড়িত কোন ingালাই
  • আপনি প্রতিটি সাবক্লাসকে আপনার পছন্দমতো ইন্টারফেস প্রয়োগ করতে পারেন যা ভবিষ্যতের পরিবর্তনের জন্য কিছুটা নমনীয়তা সরবরাহ করে।

পিএস: ইন্টারফেসগুলির নামগুলির জন্য দুঃখিত, আমি সেই নির্দিষ্ট মুহূর্তে শীতল কিছু সম্পর্কে ভাবতে পারি না: ডি।


3
এটি আসলে সমস্যার সমাধান করে না। লুপের জন্য আপনার এখনও কাস্ট দরকার। (আপনি যদি তা না করেন তবে ওপির উদাহরণে আপনার কাস্টের দরকার নেই)।
তাইমির

2

পদ্ধতির ক্ষেত্রে এমন একটি পরিস্থিতি ভাল হতে পারে যেখানে কোনও পরিবারের মধ্যে প্রায় কোনও প্রকারই হয় কিছু ইন্টারফেসের প্রয়োগ হিসাবে সরাসরি ব্যবহারযোগ্য হবে যা কিছু মানদণ্ডের সাথে মিলিত হয় বা সেই ইন্টারফেসটির একটি বাস্তবায়ন তৈরি করতে ব্যবহার করা যেতে পারে। অন্তর্নির্মিত সংগ্রহের ধরণগুলি আইএমএইচও এই প্যাটার্নটি থেকে উপকৃত হবে, তবে যেহেতু তারা উদাহরণস্বরূপ না করে আমি একটি সংগ্রহ ইন্টারফেস উদ্ভাবন করব BunchOfThings<T>

কিছু বাস্তবায়ন BunchOfThingsপরিবর্তনীয় হয়; কিছু না। অনেক ক্ষেত্রে ফ্রেড কোনও বস্তু এটি হিসাবে ব্যবহার করতে পারে এমন কিছু ধারণ করতে পারে BunchOfThingsএবং জানতে পারে ফ্রেড ব্যতীত অন্য কোনও কিছুই এটি সংশোধন করতে সক্ষম হবে না। এই প্রয়োজনীয়তা দুটি উপায়ে সন্তুষ্ট হতে পারে:

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

  2. আমরাও BunchOfThings, কিংবা তার অভ্যন্তরীণ যা বাইরে রেফারেন্স অস্তিত্ব কোন, সবটা কোনো উপায়ে মাধ্যমে পরিবর্তন করা যায়। যদি একেবারে কেউ BunchOfThingsএটিকে সংশোধন করতে না পারে তবে সীমাবদ্ধতা মেটানো হবে।

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

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

নোট করুন যে asXXপদ্ধতিগুলি কিছুটা ভিন্ন ধরণের ফিরে আসতে পারে, তবে তাদের আসল ভূমিকাটি নিশ্চিত করা হয় যে প্রত্যাবর্তিত বস্তুগুলি প্রোগ্রামের প্রয়োজনীয়তা পূরণ করবে।


0

আপনার কাছে একটি ভাল নকশা আছে কিনা তা উপেক্ষা করে এবং এটি ভাল বা কমপক্ষে গ্রহণযোগ্য বলে মনে করে, আমি ধরণের নয়, সাবক্লাসগুলির ক্ষমতা বিবেচনা করতে চাই।

অতএব, হয়:


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

if (base.canMakeASandwich()) {
    base.makeASandwich(getRandomIngredients());
    // ... etc.
} else { // can't make sandwiches, must be able to contact aliens
    base.contactAliens(getFrequency());
    // ... etc.
}

তারপরে একটি বা উভয় উপশ্রেণী ওভাররাইড করে canMakeASandwich()এবং প্রতিটি makeASandwich()এবং প্রতিটি প্রয়োগ করে contactAliens()


কোনও ধরণের কী ক্ষমতা রয়েছে তা সনাক্ত করতে কংক্রিট সাবক্লাস নয়, ইন্টারফেস ব্যবহার করুন। বেস ক্লাসটি একা ছেড়ে যান এবং কোডটি এতে পরিবর্তন করুন:

if (base instanceof SandwichMaker) {
    ((SandwichMaker)base).makeASandwich(getRandomIngredients());
    // ... etc.
} else { // can't make sandwiches, must be able to contact aliens
    ((AlienContacter)base).contactAliens(getFrequency());
    // ... etc.
}

অথবা সম্ভবত (এবং এই বিকল্পটি যদি আপনার স্টাইলের সাথে খাপ খায় না, বা জাভা শৈলীর জন্য আপনি বোধগম্য মনে করেন তবে নির্দ্বিধায়):

try {
    ((SandwichMaker)base).makeASandwich(getRandomIngredients());
} catch (ClassCastException e) {
    ((AlienContacter)base).contactAliens(getFrequency());
}

ব্যক্তিগতভাবে আমি না সাধারণত কারণ অযথাযথভাবে একটি সংক্রামক ঝুঁকি, একটি অর্ধ-প্রত্যাশিত ব্যতিক্রম ধরার আধুনিক শৈলী মত ClassCastExceptionআসছে আউট getRandomIngredientsবা makeASandwich, কিন্তু YMMV।


2
ক্লাসকাস্টএক্সেপশন ধরার সবেমাত্র পূর্বরূপ। উদাহরণস্বরূপ এটি সম্পূর্ণ উদ্দেশ্য।
রেডিওডেফ

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

@ স্টিভ জেসোপ permission অনুমতি চেয়ে ক্ষমা চাইতে আরও সহজ the স্লোগান;)
টমাস জাঙ্ক

0

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

  1. আমরা বেস ক্লাসে সমস্ত কেস কভার করতে পারি।
  2. কোনও বিদেশী উদ্ভূত শ্রেণিকে কখনও নতুন কেস যুক্ত করতে হবে না।
  3. আমরা নীতির সাথে বেচে থাকতে পারি যার জন্য বেস শ্রেণীর নিয়ন্ত্রণের অধীনে থাকার কল।
  4. তবে আমরা আমাদের বিজ্ঞান থেকে জানি যে বেস ক্লাসে নয় একটি পদ্ধতির জন্য একটি ডেরাইভেড ক্লাসে কী করা উচিত তার নীতি হ'ল ড্রেইভড ক্লাসের এবং বেস ক্লাসের নয়।

যদি 4 হয় তবে আমাদের রয়েছে: 5. উত্পন্ন শ্রেণীর নীতি সর্বদা বেস শ্রেণির নীতি হিসাবে একই রাজনৈতিক নিয়ন্ত্রণে থাকে।

2 এবং 5 উভয়ই সরাসরি বোঝায় যে আমরা সমস্ত উদ্ভূত শ্রেণি গণনা করতে পারি, যার অর্থ বাইরের কোনও উত্পন্ন শ্রেণি নেই বলে মনে হয় না।

তবে জিনিসটি এখানে। যদি এগুলি সমস্ত আপনার হয় তবে আপনি যদি প্রতিস্থাপন করতে পারেন এমন একটি বিমূর্ততা যা ভার্চুয়াল পদ্ধতি কল (এমনকি এটি কোনও বাজে কথা যদি হয়) এবং যদি এবং স্ব-কাস্ট থেকে মুক্তি পান। অতএব, এটি করবেন না। একটি ভাল নকশা উপলব্ধ।


-1

বেস ক্লাসে একটি বিমূর্ত পদ্ধতি রাখুন যা সাব 1 এ এবং একটি জিনিস সাব 2 তে করে এবং আপনার মিশ্র লুপগুলিতে সেই বিমূর্ত পদ্ধতিটিকে কল করে।

class Sub1 : Base {
    @Override void doAThing() {
        this.makeASandwich(getRandomIngredients());
    }
}

class Sub2 : Base {
    @Override void doAThing() {
        this.contactAliens(getFrequency());
    }
}

for (Base base : bases) {
    base.doAThing();
}

নোট করুন যে কীভাবে getRandomIngredient এবং getFre वारंवार সংজ্ঞা দেওয়া হয়েছে তার উপর নির্ভর করে অন্যান্য পরিবর্তনগুলির প্রয়োজন হতে পারে। তবে, সত্যই, ক্লাসের মধ্যে যে এলিয়েনদের সাথে যোগাযোগ করা সম্ভবত যাইহোক getFre ফ্রিকোয়েন্সি সংজ্ঞায়নের জন্য আরও ভাল জায়গা।

ঘটনাক্রমে, আপনার asSub1 এবং asSub2 পদ্ধতি অবশ্যই খারাপ অভ্যাস। আপনি যদি এটি করতে যাচ্ছেন তবে কাস্টিং করে এটি করুন। এই পদ্ধতিগুলি আপনাকে দেয় এমন কিছুই নেই যা castালাই করে না।


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

@ কোডড্রেকার - উদাহরণে লুপটিতে আপনি যা করছেন এটি ঠিক তার সাথে মিলে যায়। যদি এর কোনও অর্থ না থাকে তবে লুপটি লিখবেন না। যদি এটি কোনও পদ্ধতি হিসাবে অর্থবোধ না করে তবে এটি লুপ বডি হিসাবে অর্থবোধ করে না।
র্যান্ডম 832

1
এবং আপনার পদ্ধতিগুলি "গ্যারান্টি" প্রকারের সুরক্ষা একইভাবে সুরক্ষা দেয়: বস্তুটি ভুল ধরণের হলে ব্যতিক্রম ছুঁড়ে ফেলে।
র্যান্ডম 832

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

1
আমার বক্তব্যটি হ'ল আপনার কোডটি কেবল একটি রানটাইম গ্যারান্টি সরবরাহ করে। এসব 2-তে কল করার আগে কাউকে এসএস 2 পরীক্ষা করতে ব্যর্থ হতে বাধা দেওয়ার কিছুই নেই।
র্যান্ডম 832

-2

আপনি উভয় makeASandwichএবং contactAliensবেস শ্রেণিতে ঠেলাঠেলি করতে পারেন এবং তারপরে এগুলি ডামি বাস্তবায়ন সহ প্রয়োগ করতে পারেন। যেহেতু রিটার্নের ধরণ / যুক্তিগুলি একটি সাধারণ বেস শ্রেণিতে সমাধান করা যায় না।

class Sub1 extends Base{
    Sandwich makeASandwich(Ingredients i){
        //Normal implementation
    }
    boolean contactAliens(Frequency onFrequency){
        return false;
    }
 }
class Sub2 extends Base{
    Sandwich makeASandwich(Ingredients i){
        return null;
    }
    boolean contactAliens(Frequency onFrequency){
       // normal implementation
    }
 }

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


1
আমি এটি করার বিষয়ে ভেবেছিলাম, তবে এটি লিসকোভ সাবস্টিটিউশন নীতি লঙ্ঘন করে এবং এর সাথে কাজ করা যেমন খুশি নয়, যেমন, আপনি যখন "সাব 1" টাইপ করেন। এবং স্বতঃসম্পূর্ণ উঠে আসে, আপনি মেক এএসএন্ডভিচ দেখেন তবে যোগাযোগ অ্যালিয়েনস নয়।
কোডব্রেকার

-5

আপনি যা করছেন তা পুরোপুরি বৈধ। যেসব নেয়েয়াররা কেবল কুকর্মের পুনরাবৃত্তি করেছেন তাদের দিকে মনোযোগ দেবেন না কারণ তারা এটি কয়েকটি বইতে পড়েছেন। ইঞ্জিনিয়ারিংয়ে ডগমার কোনও জায়গা নেই।

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

উদাহরণস্বরূপ নিন java.lang.reflect.Member, যা এর ভিত্তি java.lang.reflect.Fieldএবং java.lang.reflect.Method। (প্রকৃত শ্রেণিবিন্যাস এর চেয়ে কিছুটা জটিল, তবে এটি অপ্রাসঙ্গিক)) ক্ষেত্র এবং পদ্ধতিগুলি বিস্তৃত বিভিন্ন প্রাণী: একটির একটি মূল্য রয়েছে যা আপনি পেতে বা সেট করতে পারেন, অন্যটির কাছে এর কোনও জিনিস নেই, তবে এটি দিয়ে প্রবেশ করা যেতে পারে with পরামিতিগুলির একটি সংখ্যা এবং এটি কোনও মান ফেরত দিতে পারে। সুতরাং, ক্ষেত্রগুলি এবং পদ্ধতিগুলি উভয়ই সদস্য, তবে আপনি যে জিনিসগুলি তাদের সাথে করতে পারেন সেগুলি স্যান্ডউইচ বনাম বনাম যোগাযোগের এলিয়েন তৈরির মতো একে অপরের থেকে আলাদা।

এখন, কোডটি লেখার সময় প্রতিবিম্বটি ব্যবহার করে Memberআমাদের হাতে প্রায়শই থাকে এবং আমরা জানি যে এটি হয় একটি Methodবা ক Field, (বা, খুব কমই, অন্য কোনও কিছু) এবং তবুও আমাদের অবাক করে instanceofদেওয়ার জন্য সমস্ত ক্লান্তিকর কাজ করতে হবে এটি কী এবং তারপরে এটির যথাযথ রেফারেন্স পেতে আমাদের এটি castালাই করতে হবে। (এবং এটি কেবল ক্লান্তিকরই নয়, তবে এটি খুব ভাল পারফর্মও করে না)) Methodশ্রেণিটি আপনি বর্ণনা করছেন এমন প্যাটার্নটি খুব সহজেই প্রয়োগ করতে পারত, এভাবে হাজার হাজার প্রোগ্রামারদের জীবন সহজ হয়ে যায়।

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

আমি এখানে যা করেছি তা আপনার কাজগুলির থেকে পৃথক:

  • বেস ক্লাসটি asDerivedClass()পদ্ধতিগুলির পুরো পরিবারের জন্য একটি ডিফল্ট বাস্তবায়ন সরবরাহ করে, যার প্রত্যেকেই ফিরে আসে null

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

  • বেস ক্লাসটি পদ্ধতিগুলির finalপুরো isDerivedClass()পরিবারের জন্য বাস্তবায়ন সরবরাহ করে, যা নীচে কোড করা হয়েছে: return asDerivedClass() != null; এইভাবে, উত্সযুক্ত শ্রেণীর দ্বারা ওভার্রাইড করা হওয়া পদ্ধতির সংখ্যা হ্রাস করা হয়।

  • আমি @Deprecatedএই প্রক্রিয়াটি ব্যবহার করছিলাম না কারণ আমি এটির কথা ভাবিনি। এখন আপনি আমাকে ধারণা দিয়েছেন, আমি এটি ব্যবহার করতে হবে, ধন্যবাদ!

সি # এর asকীওয়ার্ড ব্যবহারের মাধ্যমে অন্তর্নির্মিত একটি সম্পর্কিত পদ্ধতি রয়েছে । সি # তে আপনি বলতে পারেন DerivedClass derivedInstance = baseInstance as DerivedClassএবং আপনি DerivedClassযদি baseInstanceসেই শ্রেণীর হয়ে nullথাকেন তবে তা না থাকলে আপনি তার একটি রেফারেন্স পাবেন । এটি (তাত্ত্বিকভাবে) iscast ালু অনুসরণের চেয়ে আরও ভাল পারফরম্যান্স করে (এর isজন্য সি # কীওয়ার্ডের নাম স্বীকৃত আরও ভাল instanceof), তবে আমরা যে কাস্টম পদ্ধতিটি হ্যান্ড ক্র্যাফটিং করেছি তার থেকে আরও ভাল instanceofপারফরম্যান্স হয়: জাভা- ও -কাস্ট অপারেশনের জুটিও well asসি # এর অপারেটরটি যেমন আমাদের কাস্টম পদ্ধতির একক ভার্চুয়াল পদ্ধতি কল হিসাবে তত দ্রুত সঞ্চালন করে না।

আমি এতদ্দ্বারা ঘোষণা প্রতিজ্ঞা যে এই কৌশল হতে ঘোষণা করা হবে করা একটি প্যাটার্ন এবং যে একটা চমৎকার নাম তার জন্য পাওয়া যাবে।

জি, ডাউনভোটদের জন্য ধন্যবাদ!

বিতর্কগুলির সংক্ষিপ্তসার, আপনাকে মন্তব্যগুলি পড়ার ঝামেলা থেকে বাঁচাতে:

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

যাইহোক, আমি উপরোক্ত উদাহরণের আছে ইতিমধ্যে দেখানো যে জাভা রানটাইম এর নির্মাতাদের মধ্যে সত্য জন্য অবিকল যেমন একটি ডিজাইন চয়ন করেনি java.lang.reflect.Member, Field, Methodঅনুক্রমের, এবং মন্তব্য নীচে আমি এছাড়াও দেখায় যে C # এর রানটাইম এর নির্মাতাদের স্বাধীনভাবে একটি আগত সমতুল্য জন্য নকশা System.Reflection.MemberInfo, FieldInfo, MethodInfoঅনুক্রমের। সুতরাং, এটি দুটি পৃথক বাস্তব দৃষ্টিকোণ যা প্রত্যেকের নাকের নীচে বসে আছে এবং যা ঠিক যেমন যেমন নকশা ব্যবহার করে কার্যকরভাবে সমাধানযোগ্য সমাধান রয়েছে।

নীচের সমস্ত মন্তব্যগুলি এটিকে সেদ্ধ করে। স্ব-ingালাই প্রক্রিয়াটি খুব কমই উল্লেখ করা হয়েছে।


13
আপনি যদি নিজেকে একটি বাক্সে ডিজাইন করেন তবে এটি বৈধ sure এই ধরণের অনেক প্রশ্ন নিয়েই এটাই সমস্যা। লোকেরা ডিজাইনের অন্যান্য ক্ষেত্রে সিদ্ধান্ত নেয় যা এই ধরণের হ্যাকিশ সমাধানগুলিকে বাধ্য করে যখন সত্যিকারের সমাধানটি আপনি কেন এই পরিস্থিতিতে প্রথম স্থানে এসেছিলেন তা নির্ধারণ করার জন্য। একটি শালীন নকশা আপনাকে এখানে পাবেন না। আমি বর্তমানে 200 কে এসএলওসি অ্যাপ্লিকেশনটির দিকে তাকিয়ে আছি এবং আমাদের এটি করার দরকার ছিল এমন কোথাও দেখছি না। সুতরাং এটি কেবল মানুষ কোনও বইয়ে পড়ে কিছু নয়। এই ধরণের পরিস্থিতিতে না পাওয়া কেবল ভাল অভ্যাসগুলি অনুসরণ করার শেষ ফলাফল।
ডাঙ্ক

3
@ ডাঙ্ক আমি কেবল দেখিয়েছি যে java.lang.reflection.Memberশ্রেণিবদ্ধের মধ্যে যেমন একটি ব্যবস্থার প্রয়োজন বিদ্যমান exists জাভা রানটাইমের নির্মাতারা এই ধরণের পরিস্থিতিতে পড়েছেন, আমি মনে করি না আপনি বলবেন যে তারা নিজেরাই একটি বাক্সে নকশাকৃত, বা কোনও ধরণের সেরা অভ্যাস অনুসরণ না করার জন্য তাদের দোষ দিবে? সুতরাং, আমি এখানে যে বিষয়টি করছি তা হ'ল একবার আপনার এই ধরণের পরিস্থিতি পরে জিনিসগুলি উন্নত করার জন্য এই প্রক্রিয়াটি একটি ভাল উপায়।
মাইক নাকিস

6
@ মাইকনাকিস জাভার নির্মাতারা প্রচুর খারাপ সিদ্ধান্ত নিয়েছেন, যাতে একা একা বেশি কিছু বলে না। যে কোনও হারে, দর্শনার্থীর ব্যবহারটি অ্যাড-হক পরীক্ষা-কাস্ট করার চেয়ে ভাল।
ডোভাল

3
অতিরিক্তভাবে, উদাহরণটি ত্রুটিযুক্ত। একটি Memberইন্টারফেস আছে, তবে এটি কেবল অ্যাক্সেস যোগ্যতা যাচাই করতে পরিবেশন করে। সাধারণত, আপনি পদ্ধতি বা বৈশিষ্ট্যের একটি তালিকা পেয়ে থাকেন এবং এটি সরাসরি ব্যবহার করেন (এগুলিকে মিশ্রিত না করে, সুতরাং কোনও List<Member>উপস্থিত হয় না), তাই আপনাকে কাস্ট করার দরকার নেই। নোট যা Classকোনও getMembers()পদ্ধতি সরবরাহ করে না । অবশ্যই, একটি ক্লুলেস প্রোগ্রামার এটি তৈরি করতে পারে List<Member>তবে এটি এটিকে তৈরি করা List<Object>এবং কিছু Integerবা Stringএটি যুক্ত করার মতো সামান্যই বোধগম্য হবে।
এসজুয়ান 76

5
@ মাইকনাকিস "প্রচুর লোকেরা এটি করে" এবং "বিখ্যাত ব্যক্তি এটি করেন" আসল যুক্তি নয়। অ্যান্টিপ্যাটার্নগুলি উভয়ই খারাপ ধারণা এবং সংজ্ঞা দ্বারা ব্যাপকভাবে ব্যবহৃত হয়, তবুও এই অজুহাতগুলি তাদের ব্যবহারকে ন্যায়সঙ্গত করে তোলে। কিছু ডিজাইন বা অন্য ব্যবহার করার প্রকৃত কারণ দিন। অ্যাড-হক কাস্টিংয়ের সাথে আমার সমস্যাটি হ'ল আপনার এপিআই এর প্রত্যেক ব্যবহারকারীকে প্রতিবারই কাস্টিং ঠিক করা উচিত। একজন দর্শনার্থীর জন্য একবারে সঠিক হওয়া দরকার। কিছু পদ্ধতির পিছনে কাস্টিং লুকিয়ে রাখা এবং nullকোনও ব্যতিক্রমের পরিবর্তে ফিরে আসা আরও ভাল করে তোলে না। সমস্ত কিছু সমান হওয়ায়, একই কাজটি করার সময় দর্শক নিরাপদ is
ডোভাল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.