Development Tip

상속을 통해 열거 형 확장

yourdevel 2020. 10. 6. 19:33
반응형

상속을 통해 열거 형 확장


나는 이것이 enum의 개념에 반한다는 것을 알고 있지만 C # / Java에서 enum을 확장 할 수 있습니까? 열거 형에 새 값을 추가하는 의미에서 "확장"을 의미하지만 기존 열거 형에서 상속하는 OO 의미에서도 마찬가지입니다.

자바에서는 가능하지 않다고 생각합니다. 꽤 최근에 나온 것입니다 (Java 5?). C #은 미친 짓을하려는 사람들을 더 관대 해 보였기 때문에 어떤 식 으로든 가능할 것이라고 생각했습니다. 아마도 리플렉션을 통해 해킹 당할 수 있습니까? (실제로 모든 방법을 사용하는 것은 아닙니다)?

나는 주어진 방법을 구현하는 데 반드시 관심이있는 것은 아니며, 그것이 나에게 일어 났을 때 호기심을 불러 일으켰습니다. :-)


Enum을 확장 할 수없는 이유는 다형성 문제로 이어지기 때문입니다.

값이 A, B 및 C 인 열거 형 MyEnum이 있고이를 MyExtEnum 값으로 D 값으로 확장한다고 가정합니다.

메소드가 예를 들어 매개 변수로 myEnum 값을 어딘가에 예상한다고 가정하십시오. 하위 유형이기 때문에 MyExtEnum 값을 제공하는 것이 합법적이어야하지만 이제 값이 D 인 것으로 밝혀지면 무엇을 하시겠습니까?

이 문제를 해결하기 위해 열거 형을 확장하는 것은 불법입니다.


내장 된 열거 형으로 충분하지 않은 경우, 구식 방식으로 수행하고 직접 만들 수 있습니다. 예를 들어 설명 필드와 같은 추가 속성을 추가하려는 경우 다음과 같이 할 수 있습니다.

public class Action {
    public string Name {get; private set;}
    public string Description {get; private set;}

    private Action(string name, string description) {
        Name = name;
        Description = description;
    }

    public static Action DoIt = new Action("Do it", "This does things");
    public static Action StopIt = new Action("Stop It", "This stops things");
}

그런 다음 다음과 같이 열거 형으로 처리 할 수 ​​있습니다.

public void ProcessAction(Action a) {
    Console.WriteLine("Performing action: " + a.Name)
    if (a == Action.DoIt) {
       // ... and so on
    }
}

트릭은 생성자가 비공개 (또는 상속하려는 경우 보호됨)이고 인스턴스가 정적인지 확인하는 것입니다.


잘못된 방향으로 가고 있습니다. 열거 형의 하위 클래스에는 항목 적을 것 입니다.

의사 코드에서 다음을 생각하십시오.

enum Animal { Mosquito, Dog, Cat };
enum Mammal : Animal { Dog, Cat };  // (not valid C#)

동물을 받아 들일 수있는 모든 방법은 포유류를 받아 들일 수 있어야하지만 그 반대는 아닙니다. 서브 클래 싱은 더 일반적인 것이 아니라 더 구체적으로 만드는 것입니다. 이것이 "객체"가 클래스 계층 구조의 루트 인 이유입니다. 마찬가지로, 열거 형이 상속 가능한 경우 열거 형 계층 구조의 가상 루트에는 가능한 모든 기호가 있습니다.

그러나 아니요, C # / Java는 하위 열거 형 AFAICT를 허용하지 않습니다.하지만 때때로 정말 유용 할 것입니다. 아마도 그들은 인턴 심볼 (예 : Lisp) 대신에 Int (예 : C)로 Enum을 구현하기로 선택했기 때문일 것입니다. (위에서 (Animal) 1은 무엇을 나타내고, (Mammal) 1은 무엇을 나타내며, 동일한 값입니까?)

그러나 이것을 제공하는 자신의 열거 형 클래스 (다른 이름으로)를 작성할 수 있습니다. C # 속성을 사용하면 멋지게 보일 수도 있습니다.


열거 형은 가능한 모든 값의 열거 형을 나타내야하므로 확장은 오히려 아이디어에 어긋납니다.

그러나 Java (그리고 아마도 C ++ 0x)에서 할 수있는 것은 열거 형 클래스 대신 인터페이스를 갖는 것입니다. 그런 다음 기능을 구현하는 열거 형에 표준 값을 입력합니다. 분명히 당신은 java.util.EnumSet 등을 사용하지 않습니다. 이것은 JDK7에 있어야하는 "더 많은 NIO 기능"에서 취해진 접근 방식입니다.

public interface Result {
    String name();
    String toString();
}
public enum StandardResults implements Result {
    TRUE, FALSE
}


public enum WTFResults implements Result {
    FILE_NOT_FOUND
}

당신은 실행시에 기존의 열거에서 레이블과 값을 검색 할 .NET 반사를 사용할 수 있습니다 ( Enum.GetNames()그리고 Enum.GetValues()당신이 사용하는 것과 두 가지 특정 방법입니다) 그리고 이러한 요소를 더한 새로운 사람과 새로 만들 코드 주입을 사용. 이것은 "기존 열거 형에서 상속"과 다소 유사 해 보입니다.


열거 형을 추가하는 것은 소스 코드로 돌아가서 편집하는 경우에 수행하는 매우 일반적인 작업입니다. 다른 방법 (가능한 경우 상속 또는 반영)이 다시 돌아와 라이브러리를 업그레이드 할 때 타격을 입힐 수 있습니다. 그들은 동일한 열거 형 이름 또는 동일한 열거 형 값 을 도입했습니다 . 정수 숫자가 바이너리 인코딩과 일치하는 저수준 코드를 많이 보았습니다. 여기서 문제가 발생합니다.

이상적으로 열거 형을 참조하는 코드는 같음 (또는 스위치)으로 작성되어야하며, 열거 형 집합이 const가 될 것으로 예상하지 않음으로써 미래의 증거가되어야합니다.


Base 클래스 의미에서 확장을 의미한다면 Java에서 ... 아니요.

그러나 그것이 의미하는 경우 속성과 메서드를 갖도록 열거 형 값을 확장 할 수 있습니다.

예를 들어 다음은 대괄호 열거 형을 사용합니다.

class Person {
    enum Bracket {
        Low(0, 12000),
        Middle(12000, 60000),
        Upper(60000, 100000);

        private final int low;
        private final int high;
        Brackets(int low, int high) {
            this.low = low;
            this.high = high;
        }

        public int getLow() {
            return low;
        }

        public int getHigh() {
            return high;
        }

        public boolean isWithin(int value) {
           return value >= low && value <= high;
        }

        public String toString() {
            return "Bracket " + low + " to " + high;
        }
    }

    private Bracket bracket;
    private String name;

    public Person(String name, Bracket bracket) {
        this.bracket = bracket;
        this.name = name;
    }

    public String toString() {
        return name + " in " + bracket;
    }        
}

I didn't see anyone else mention this but the ordinal value of an enum is important. For example, with grails when you save an enum to the database it uses the ordinal value. If you could somehow extend an enum, what would be the ordinal values of your extensions? If you extended it in multiple places how could you preserve some kind of order to these ordinals? Chaos/instability in the ordinal values would be a bad thing which is probably another reason why the language designers have not touched this.

Another difficulty if you were the language designer, how can you preserve the functionality of the values() method which is supposed to return all of the enum values. What would you invoke this on and how would it gather up all of the values?


Saw a post regarding this for Java a while back, check out http://www.javaspecialists.eu/archive/Issue161.html .


You can't inherit from/extend an enum, you can use attributes to declare a description. If you're looking for an integer value, that's built-in.


Hmmm - as far as I know, this can't be done - enumerations are written at design-time and are used as a convenience to the programmer.

I'm pretty sure that when the code is compiled, the equivalent values will be substituted for the names in your enumeration, thereby removing the concept of an enumeration and (therefore) the ability to extend it.


I would like to be able to add values to C# enumerations which are combinations of existing values. For example (this is what I want to do):

AnchorStyles is defined as

public enum AnchorStyles { None = 0, Top = 1, Bottom = 2, Left = 4, Right = 8, }

and I would like to add an AnchorStyles.BottomRight = Right + Bottom so instead of saying

my_ctrl.Anchor = AnchorStyles.Right | AnchorStyles.Bottom;

I can just say

my_ctrl.Anchor = AnchorStyles.BottomRight;

This doesn't cause any of the problems that have been mentioned above, so it would be nice if it was possible.


Some time back even i wanted to do something like this and found that enum extensions would voilate lot of basic concepts... (Not just polymorphisim)

But still u might need to do if the enum is declared in external library and Remember you should make a special caution when using this enum extensions...

public enum MyEnum { A = 1, B = 2, C = 4 }

public const MyEnum D = (MyEnum)(8);
public const MyEnum E = (MyEnum)(16);

func1{
    MyEnum EnumValue = D;

    switch (EnumValue){
      case D:  break;
      case E:  break;
      case MyEnum.A:  break;
      case MyEnum.B:  break;
   }
}

As far as java is concerned it is not allowed because adding elements to an enum would effectively create a super class rather than a sub class.

Consider:

 enum Person (JOHN SAM}   
 enum Student extends Person {HARVEY ROSS}

A general use case of Polymorphism would be

 Person person = Student.ROSS;   //not legal

which is clearly wrong.

참고URL : https://stackoverflow.com/questions/55375/extending-an-enum-via-inheritance

반응형