Расширение перечисления через наследование

Спасибо, всем. Я тестировал фрагменты кода здесь в последних браузерах: Chrome 55, Firefox 50, IE 11 и Edge 38 и я придумали следующую комбинацию, которая работала для меня для всех. Я уверен, что его можно улучшить, но это быстрое решение для тех, кому это нужно:

var browser_name = '';
isIE = /*@cc_on!@*/false || !!document.documentMode;
isEdge = !isIE && !!window.StyleMedia;
if(navigator.userAgent.indexOf("Chrome") != -1 && !isEdge)
{
    browser_name = 'chrome';
}
else if(navigator.userAgent.indexOf("Safari") != -1 && !isEdge)
{
    browser_name = 'safari';
}
else if(navigator.userAgent.indexOf("Firefox") != -1 ) 
{
    browser_name = 'firefox';
}
else if((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true )) //IF IE > 10
{
    browser_name = 'ie';
}
else if(isEdge)
{
    browser_name = 'edge';
}
else 
{
   browser_name = 'other-browser';
}
$('html').addClass(browser_name);

Он добавляет класс CSS в HTML с именем браузера.

80
задан Steve Chambers 26 March 2015 в 12:23
поделиться

13 ответов

Причина Вы не можете расширить Перечисления, состоит в том, потому что она привела бы к проблемам с полиморфизмом.

Говорят, что Вы имеете перечислимый MyEnum со значениями A, B, и C, и расширяете его с помощью значения D как MyExtEnum.

предположим метод ожидает значение myEnum где-нибудь, например, в качестве параметра. Должно быть законно предоставить значение MyExtEnum, потому что это - подтип, но теперь что Вы собираетесь сделать, когда это складывается, значение является D?

Для устранения этой проблемы расширение перечислений недопустимо

102
ответ дан Rik 24 November 2019 в 09:49
поделиться

Hmmm - насколько я знаю, это не может быть сделано - перечисления записаны во время проектирования и используются в качестве удобства программисту.

я вполне уверен, что, когда код компилируется, эквивалентными стоимостями заменят имена в Вашем перечислении, таким образом, удаляя понятие перечисления и (поэтому) способности расширить его.

0
ответ дан Chris Roberts 24 November 2019 в 09:49
поделиться

Вы не можете наследоваться перечислению, можно использовать , атрибуты к объявляют описание . Если Вы ищете целочисленное значение, это встроено.

0
ответ дан bdukes 24 November 2019 в 09:49
поделиться

Видел, что сообщение расценило это для Java некоторое время назад, проверьте http://www.javaspecialists.eu/archive/Issue161.html .

1
ответ дан jwiklund 24 November 2019 в 09:49
поделиться

Добавление перечислений является довольно общей вещью сделать, если Вы вернетесь к исходному коду и редактированию, то любой другой путь (наследование или отражение, если любой возможен), вероятно, возвратится и поражать Вас, когда Вы получите обновление библиотеки, и они представили то же перечислимое имя или то же перечисление значений - я видел много кода низкого уровня, где целое число соответствует к двоичному кодированию, где Вы столкнулись бы с проблемами

Идеально, перечисления ссылки кода должны быть записаны, как равняется только (или переключатели), и попытайтесь соответствовать требованиям завтрашнего дня, не ожидая, что перечислимый набор будет константой

2
ответ дан Oskar 24 November 2019 в 09:49
поделиться

Можно использовать отражение.NET для получения маркировок и значений от существующего перечисления во времени выполнения (Enum.GetNames(), и Enum.GetValues() два определенных метода, которые Вы использовали бы), и затем используйте инжекцию кода для создания новой с теми элементами плюс некоторые новые. Это кажется несколько analagous "наследованию от существующего перечисления".

3
ответ дан McKenzieG1 24 November 2019 в 09:49
поделиться

Перечисления, как предполагается, представляют перечисление всех возможных значений, таким образом расширение скорее идет вразрез с идеей.

Однако то, что можно сделать в Java (и по-видимому C++ 0x), имеют интерфейс вместо класса Enum. Тогда поместите Вас стандартные значения в перечисление, которое реализует опцию. Очевидно, Вы не добираетесь для использования java.util. EnumSet и т.п.. Это - подход, проявленный в "большем количестве функций NIO", которые должны быть в JDK7.

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


public enum WTFResults implements Result {
    FILE_NOT_FOUND
}
12
ответ дан Tom Hawtin - tackline 24 November 2019 в 09:49
поделиться

Когда встроенные перечисления не достаточно, можно сделать это старомодный путь и обработать собственное. Например, если бы Вы хотели добавить дополнительное свойство, например, поле описания, Вы могли бы сделать это следующим образом:

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
    }
}

прием должен удостовериться, что конструктор является частным (или защищенный, если Вы хотите наследоваться), и что Ваши экземпляры статичны.

41
ответ дан tsimon 24 November 2019 в 09:49
поделиться

Если Вы имеете в виду, расширяется в смысле Базового класса, то в 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;
    }        
}
2
ответ дан Allain Lalonde 24 November 2019 в 09:49
поделиться

А временное/локальное обходное решение , когда Вы просто хотите очень локальное/одно использование времени:

enum Animals { Dog, Cat }
enum AnimalsExt { Dog = Animals.Dog, Cat= Animals.Cat,  MyOther}
// BUT CAST THEM when using:
var xyz = AnimalsExt.Cat;
MethodThatNeedsAnimal(   (Animals)xyz   );

См. все ответы в: Перечисление " Inheritance"

0
ответ дан 24 November 2019 в 09:49
поделиться

Вы идете неверным путем: подкласс перечисления будет иметь на меньше записей.

В псевдокоде подумайте:

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

Любой метод, который может принимать Животное должно быть способно принять Млекопитающее, но не наоборот. Создание подклассов предназначено для создания чего-то более конкретного, а не более общего. Вот почему «объект» является корнем иерархии классов. Точно так же, если бы перечисления были наследуемыми, то гипотетический корень иерархии перечислений имел бы все возможные символы.

Но нет, C # / Java не допускает подперечислений, AFAICT, хотя иногда это было бы действительно полезно. Вероятно, это потому, что они решили реализовать Enums как int (например, C) вместо интернированных символов (например, Lisp). (Выше, что представляет (Животное) 1 и что представляет (Млекопитающее) 1, и имеют ли они одно и то же значение?)

Вы могли бы написать свой собственный enum-подобный класс (с другим именем), который бы это предоставлял. С атрибутами C # это могло бы даже выглядеть неплохо.

39
ответ дан 24 November 2019 в 09:49
поделиться

Я не видел, чтобы кто-то еще упоминал об этом, но порядковый номер перечисления важен. Например, с grails, когда вы сохраняете перечисление в базе данных, оно использует порядковое значение. Если бы вы могли каким-то образом расширить перечисление, каковы были бы порядковые значения ваших расширений? Если вы расширили его в нескольких местах, как бы вы могли сохранить какой-то порядок в этих порядковых номерах? Хаос / нестабильность в порядковых значениях - это плохо, что, вероятно, является еще одной причиной, по которой разработчики языка не коснулись этого.

Еще одна трудность, если вы были разработчиком языка, как сохранить функциональность метода values ​​(), который должен возвращать все значения перечисления. Что бы вы использовали для этого и как бы он собрал все значения?

2
ответ дан 24 November 2019 в 09:49
поделиться

Я хотел бы иметь возможность добавлять значения в перечисления C #, которые представляют собой комбинации существующих значений. Например (это то, что я хочу сделать):

AnchorStyles определяется как

public enum AnchorStyles { Нет = 0, Верх = 1, Внизу = 2, Left = 4, Вправо = 8, }

и я хотел бы добавить AnchorStyles.BottomRight = Right + Bottom, поэтому вместо того, чтобы говорить

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

, я могу просто сказать

my_ctrl.Anchor = AnchorStyles.BottomRight;

Это не вызывает никаких проблем, которые были упомянуты выше, поэтому это будет будь милым, если бы это было возможно.

0
ответ дан 24 November 2019 в 09:49
поделиться