কেন একটি এনাম একটি ইন্টারফেস প্রয়োগ করবে?


193

আমি সবেমাত্র জানতে পেরেছিলাম যে জাভা এনামগুলিকে একটি ইন্টারফেস বাস্তবায়নের অনুমতি দেয়। তার জন্য কী ভাল ব্যবহারের মামলা হবে?


উত্তর:


130

এনামগুলিকে কেবল প্যাসিভ সেট (যেমন রঙ) উপস্থাপন করতে হবে না। এগুলি কার্যকারিতা সহ আরও জটিল বস্তুগুলির প্রতিনিধিত্ব করতে পারে এবং তাই আপনি এরপরে আরও কার্যকারিতা যুক্ত করতে চান - যেমন আপনার ইন্টারফেসগুলি থাকতে পারে Printable, Reportableইত্যাদি এবং উপাদানগুলি সমর্থন করে এমন উপাদানগুলি।


259

এখানে একটি উদাহরণ (কার্যকর জাভা দ্বিতীয় সংস্করণে অনুরূপ / আরও ভাল একটি পাওয়া যায়):

public interface Operator {
    int apply (int a, int b);
}

public enum SimpleOperators implements Operator {
    PLUS { 
        int apply(int a, int b) { return a + b; }
    },
    MINUS { 
        int apply(int a, int b) { return a - b; }
    };
}

public enum ComplexOperators implements Operator {
    // can't think of an example right now :-/
}

এখন সাধারণ + কমপ্লেক্স অপারেটর উভয়ের একটি তালিকা পেতে:

List<Operator> operators = new ArrayList<Operator>();

operators.addAll(Arrays.asList(SimpleOperators.values()));
operators.addAll(Arrays.asList(ComplexOperators.values()));

সুতরাং এখানে আপনি এক্সটেনসিবল এনামগুলিকে অনুকরণ করতে একটি ইন্টারফেস ব্যবহার করেন (যা কোনও ইন্টারফেস ব্যবহার না করে সম্ভব হবে না)।


3
কমপ্লেক্স অপারেটরগুলি "পাওয়ার" এবং এর মতো হতে পারে।
পিমগড

2
প্রথমবারের মতো এনাম সিনট্যাক্সটি দেখে (সদস্যদের পরে কোঁকড়ানো ধনুর্বন্ধনী সহ), এবং আমি জাভা দিয়ে 6 বছর ধরে প্রোগ্রামিং করছি। তিল।
rahরহালি

23

Comparableউদাহরণস্বরূপ কয়েক জনের কর্তৃক প্রদত্ত এখানে ভুল, যেহেতু Enumইতিমধ্যে কার্যকরী হয়। আপনি এটি ওভাররাইডও করতে পারবেন না।

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

interface DataType {
  // methods here
}

enum SimpleDataType implements DataType {
  INTEGER, STRING;

  // implement methods
}

class IdentifierDataType implements DataType {
  // implement interface and maybe add more specific methods
}

2
হ্যাঁ.উয়ার্ড !!। এনাম ইতিমধ্যে তুলনামূলক ইন্টারফেস প্রয়োগ করে এবং ওভাররাইড করার অনুমতি দেয় না। আমি এনাম ক্লাসের জন্য জাভা উত্স কোডটি সন্ধান করেছি এবং তুলনা করার বাস্তবায়নটি খুঁজে পাইনি। কেউ কি আমাকে বলতে পারবেন একটি তুলনামূলক পদ্ধতিতে কোন ENUM এর সাথে কি তুলনা করা হয়?
AKh

2
@ এএইচটি অর্ডিনালের সাথে তুলনা করে, যার অর্থ প্রাকৃতিক ক্রম হ'ল এনাম কনস্ট্যান্টগুলি উত্স ফাইলে থাকা ক্রম।
উয়র্ন

এনাম ভার্সগুলি চূড়ান্ত এবং তাই তুলনা ঘটে == এর সাথে, ডান?
djangofan

@ ডিজেঙ্গোফান হ্যাঁ
উয়র্ন

17

আমি প্রায়শই ব্যবহার করি এমন একটি মামলা রয়েছে। IdUtilখুব সাধারণ Identifiableইন্টারফেস প্রয়োগকারী অবজেক্টের সাথে কাজ করার জন্য আমার স্ট্যাটিক পদ্ধতি সহ একটি বর্গ রয়েছে :

public interface Identifiable<K> {
    K getId();
}


public abstract class IdUtil {

    public static <T extends Enum<T> & Identifiable<S>, S> T get(Class<T> type, S id) {
        for (T t : type.getEnumConstants()) {
            if (Util.equals(t.getId(), id)) {
                return t;
            }
        }
        return null;
    }

    public static <T extends Enum<T> & Identifiable<S>, S extends Comparable<? super S>> List<T> getLower(T en) {
        List<T> list = new ArrayList<>();
        for (T t : en.getDeclaringClass().getEnumConstants()) {
             if (t.getId().compareTo(en.getId()) < 0) {
                 list.add(t);
            }
        }
        return list;
    }
}

যদি আমি এটি তৈরি করি Identifiable enum:

    public enum MyEnum implements Identifiable<Integer> {

        FIRST(1), SECOND(2);

        private int id;

        private MyEnum(int id) {
            this.id = id;
        }

        public Integer getId() {
            return id;
        }

    }

তারপরে আমি এটি idএইভাবে এটি পেতে পারি :

MyEnum e = IdUtil.get(MyEnum.class, 1);

13

যেহেতু এনামগুলি ইন্টারফেস প্রয়োগ করতে পারে সেগুলি সিঙ্গলটন নিদর্শনটির কঠোর প্রয়োগের জন্য ব্যবহার করা যেতে পারে। একটি স্ট্যান্ডার্ড ক্লাস করার চেষ্টা করে সিঙ্গলটন অনুমতি দেয় ...

  • জনসাধারণ হিসাবে ব্যক্তিগত পদ্ধতি প্রকাশ করার জন্য প্রতিবিম্ব কৌশল ব্যবহারের সম্ভাবনার জন্য
  • আপনার সিঙ্গলটন থেকে উত্তরাধিকার সূত্রে প্রাপ্ত এবং অন্য কিছু দিয়ে আপনার সিঙ্গলটনের পদ্ধতিগুলিকে ওভাররাইড করার জন্য

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

দেখুন /programming/427902/java-enum-singleton এবং জাভা একক বর্গ আরো আলোচনার জন্য।


1
for inheriting from your singleton and overriding your singleton's methods with something else। এটি final classরোধ করতে আপনি কেবল একটি ব্যবহার করতে পারেন
ডিলান্থেপিগুয়ে

10

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

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


7

এনামগুলি ছদ্মবেশে কেবল ক্লাস হয় তাই বেশিরভাগ অংশের জন্য, আপনি এনামের সাথে ক্লাসের সাথে যা কিছু করতে পারেন।

আমি কোনও কারণ ভাবতে পারি না যে কোনও এনাম কোনও ইন্টারফেস কার্যকর করতে সক্ষম না হওয়া উচিত, একই সাথে আমি তাদের উভয়ের পক্ষে কোনও ভাল কারণও ভাবতে পারি না।

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


4
"... সুতরাং বেশিরভাগ অংশের জন্য আপনি এনামের সাথে যে ক্লাস করতে পারেন তা করতে পারেন", তবুও আমি বলতে পারি না যে আমার এনামটি একটি বিমূর্ত শ্রেণীর উত্তরাধিকারী হবে। হ্যাঁ, "বেশিরভাগ অংশের জন্য" জোর দিন।
অ্যাডাম পার্কিন

5
এজন্য যে enums সমস্ত java.lang.Enum এবং জাভা ক্লাস কেবল একটি শ্রেণি থেকে প্রসারিত করতে পারে।
তোফুবিয়ার

6

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


6

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


5

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

import java.util.ArrayList;
import java.util.Collection;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;


public class Test {
    public final static String DEFAULT_COMPONENT = "Default";

    enum FilterTest implements Predicate {
        Active(false) {
            @Override
            boolean eval(Test test) {
                return test.active;
            }
        },
        DefaultComponent(true) {
            @Override
            boolean eval(Test test) {
                return DEFAULT_COMPONENT.equals(test.component);
            }
        }

        ;

        private boolean defaultValue;

        private FilterTest(boolean defautValue) {
            this.defaultValue = defautValue;
        }

        abstract boolean eval(Test test);

        public boolean evaluate(Object o) {
            if (o instanceof Test) {
                return eval((Test)o);
            }
            return defaultValue;
        }

    }

    private boolean active = true;
    private String component = DEFAULT_COMPONENT;

    public static void main(String[] args) {
        Collection<Test> tests = new ArrayList<Test>();
        tests.add(new Test());

        CollectionUtils.filter(tests, FilterTest.Active);
    }
}

5

উল্লিখিত কৌশলগুলি উপরের পোস্টটি এনামগুলি ব্যবহার করে কৌশল প্যাটার্নটির একটি সুন্দর হালকা ওজনের বাস্তবায়ন আপনাকে যথেষ্ট পরিমাণে চাপ দেয়নি:

public enum Strategy {

  A {
    @Override
    void execute() {
      System.out.print("Executing strategy A");
    }
  },

  B {
    @Override
    void execute() {
      System.out.print("Executing strategy B");
    }
  };

  abstract void execute();
}

প্রত্যেকের জন্য পৃথক সংকলন ইউনিটের প্রয়োজন ছাড়াই আপনার সমস্ত কৌশল এক জায়গায় থাকতে পারে। আপনি ঠিক এর সাথে একটি দুর্দান্ত গতিশীল প্রেরণা পান:

Strategy.valueOf("A").execute();

জাভা প্রায় একটি দুর্দান্ত lyিলে !ালা টাইপের ভাষার মতো পড়ায়!


3

এনামগুলি জাভা ক্লাসগুলির মতো হয়, তাদের কাছে কনস্ট্রাক্টর, পদ্ধতি ইত্যাদি থাকতে পারে আপনি কেবল তাদের সাথে না করতে পারেন new EnumName()। উদাহরণগুলি আপনার এনাম ঘোষণায় পূর্বনির্ধারিত।


কি হবে enum Foo extends SomeOtherClass? একটি নিয়মিত ক্লাস হিসাবে তাই একই জিনিস না, আসলে, বেশ ভিন্ন।
অ্যাডাম পার্কিন

@ অ্যাডাম: আমি বলব যে এনামগুলি যেভাবে ক্লাসগুলির সাথে সাদৃশ্যপূর্ণ সেগুলি ক্লাস থেকে পৃথক হওয়ার চেয়ে অনেক বেশি। তবে, না, তারা অভিন্ন নয়।
স্কটব

যদি আপনি একটি এনামকে সংশ্লেষ করেন তবে আপনি দেখতে পাবেন এটি একটি শ্রেণি যা গণনা প্রসারিত করে এবং "কনস্ট্যান্টস" ইতিমধ্যে কনস্ট্রাক্টর / ইনিশিয়েশন ক্ষেত্রগুলিতে ইনস্ট্যান্টেশনযুক্ত।
কসমিন কসমিন

3

আরেকটি সার্থকতা:

public enum ConditionsToBeSatisfied implements Predicate<Number> {
    IS_NOT_NULL(Objects::nonNull, "Item is null"),
    IS_NOT_AN_INTEGER(item -> item instanceof Integer, "Item is not an integer"),
    IS_POSITIVE(item -> item instanceof Integer && (Integer) item > 0, "Item is negative");

    private final Predicate<Number> predicate;
    private final String notSatisfiedLogMessage;

    ConditionsToBeSatisfied(final Predicate<Number> predicate, final String notSatisfiedLogMessage) {
        this.predicate = predicate;
        this.notSatisfiedLogMessage = notSatisfiedLogMessage;
    }

    @Override
    public boolean test(final Number item) {
        final boolean isNotValid = predicate.negate().test(item);

        if (isNotValid) {
            log.warn("Invalid {}. Cause: {}", item, notSatisfiedLogMessage);
        }

        return predicate.test(item);
    }
}

এবং ব্যবহার:

Predicate<Number> p = IS_NOT_NULL.and(IS_NOT_AN_INTEGER).and(IS_POSITIVE);

3

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

প্রদত্ত:

public interface Color {
  String fetchName();
}

এবং:

public class MarkTest {

  public static void main(String[] args) {
    MarkTest.showColor(Colors.BLUE);
    MarkTest.showColor(MyColors.BROWN);
  }

  private static void showColor(Color c) {
    System.out.println(c.fetchName());
  }
}

একটি জার মধ্যে একটি এনাম থাকতে পারে:

public enum Colors implements Color {
  BLUE, RED, GREEN;
  @Override
  public String fetchName() {
    return this.name();
  }
}

এবং কোনও ব্যবহারকারী তার নিজস্ব রঙ যুক্ত করতে এটি প্রসারিত করতে পারে:

public enum MyColors implements Color {
  BROWN, GREEN, YELLOW;
  @Override
  public String fetchName() {
    return this.name();
  }
}

2

আমার কারণ এখানে ...

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

আমি আমার কম্বোবক্স তালিকায় একটি পরিচয় মানের জন্য একটি মিল খুঁজে পেতে চাই। এনাম মানযুক্ত আমার কম্বোবক্সে এই ক্ষমতাটি ব্যবহার করার জন্য, অবশ্যই আমার এনুমে সনাক্তকরণযোগ্য ইন্টারফেসটি প্রয়োগ করতে সক্ষম হব (যা এটি ঘটে যেমন একটি এনামের ক্ষেত্রে প্রয়োগ করার জন্য তুচ্ছ)।


1

আমি একটি ইন্টারফেসে একটি অভ্যন্তরীণ এনাম ব্যবহার করেছি সেখান থেকে উদাহরণ নিয়ন্ত্রণ রাখতে প্রতিটি কৌশল (প্রতিটি কৌশলই সিঙ্গলটন)।

public interface VectorizeStrategy {

    /**
     * Keep instance control from here.
     * 
     * Concrete classes constructors should be package private.
     */
    enum ConcreteStrategy implements VectorizeStrategy {
        DEFAULT (new VectorizeImpl());

        private final VectorizeStrategy INSTANCE;

        ConcreteStrategy(VectorizeStrategy concreteStrategy) {
            INSTANCE = concreteStrategy;
        }

        @Override
        public VectorImageGridIntersections processImage(MarvinImage img) {
            return INSTANCE.processImage(img);
        }
    }

    /**
     * Should perform edge Detection in order to have lines, that can be vectorized.
     * 
     * @param img An Image suitable for edge detection.
     * 
     * @return the VectorImageGridIntersections representing img's vectors 
     * intersections with the grids.
     */
    VectorImageGridIntersections processImage(MarvinImage img);
}

এনাম এই কৌশলটি প্রয়োগ করে তা এনাম শ্রেণিকে তার বদ্ধ দৃষ্টান্তের জন্য প্রক্সি হিসাবে কাজ করার অনুমতি দেওয়ার পক্ষে সুবিধাজনক। যা ইন্টারফেস প্রয়োগ করে।

এটি এক ধরণের কৌশল এনামপ্রক্সি: পি ক্লেন্ট কোডটি দেখতে এই রকম:

VectorizeStrategy.ConcreteStrategy.DEFAULT.processImage(img);

যদি এটি ইন্টারফেসটি বাস্তবায়ন না করে তবে এটি করা হত:

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