Base Enum Class Inheritance

Base enum class inheritance

Not possible. There is no inheritance with enums.

You can instead use classes with named const ints.

Example:

class Colors
{
public:
static const int RED = 1;
static const int GREEN = 2;
};

class RGB : public Colors
{
static const int BLUE = 10;
};


class FourColors : public Colors
{
public:
static const int ORANGE = 100;
static const int PURPLE = 101;
};

Enums support for inheritance

No, C++ does not allow this sort of thing. Base::Color is a completely separate type from Derived::Color, with zero connection to them. This is no different from any other nested types; nested types defined in a base class are not connected to nested types defined in a derived class.

Nor can enumerations be inherited from one another.

This sort of things tends to go against good OOP practices anyway. After all, if a derived class introduces a new enumerator, how would the base class handle it? How would different derived class instances handle it?

If Base defines an operation over an enumeration, then Base defines the totality of the enumeration it operates on, and every class derived from it ought to be able to handle all of those options. Otherwise, something is very wrong with your virtual interface.

Enum Inheritance

This is not possible. Enums cannot inherit from other enums. In fact all enums must actually inherit from System.Enum. C# allows syntax to change the underlying representation of the enum values which looks like inheritance, but in actuality they still inherit from System.enum.

See section 8.5.2 of the CLI spec for the full details. Relevant information from the spec

  • All enums must derive from System.Enum
  • Because of the above, all enums are value types and hence sealed

How to enable enum inheritance

You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.

However, enums can implement interfaces.

What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.

Then your enum values would be referred to by their common interface.

In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.

That would force implementing enums to provide an implementation for that method.

This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.

Self-contained example (don't mind the lazy names here)

package test;

import java.util.ArrayList;
import java.util.List;

public class Main {

public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}

static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}

Output

first
POST

How to extend Python Enum?

Subclassing an enumeration is allowed only if the enumeration does not define any members.

Allowing subclassing of enums that define members would lead to a violation of some important invariants of types and instances.

https://docs.python.org/3/library/enum.html#restricted-enum-subclassing

So no, it's not directly possible.

Extending enum in derived classes

From the OO standpoint, it is not reasonable. Since you say that DerivedException is-a BaseException, its possible reasons must be a subset of that of BaseException, not a superset. Otherwise you ultimately break the Liskov Substitution Principle.

Moreover, since C++ enums are not classes, you can't extend or inherit them. You can define additional reasons in a separate enum within DerivedException, but then ultimately you bump into the same problem described above:

class DerivedException : public BaseException
{
enum {
SOME_OTHER_REASON = THAT_REASON + 256, // allow extensions in the base enum
AND_ANOTHER_REASON
};
...
};

...
try {
...
} catch (BaseException& ex) {
if (ex.getReason() == BaseException::THIS_REASON)
...
else if (ex.getReason() == BaseException::THAT_REASON)
...
else if (ex.getReason() == ??? what to test for here ???)
...
}

What you can do instead is define a separate exception subclass for each distinct reason. Then you can handle them polymorphically (if needed). This is the approach of the standard C++ library as well as other class libraries. Thus you adhere to the conventions, which makes your code easier to understand.

Enum inheriting from primitive type

This does not mean inheritance, this selects the enum's underlying type. The underlying type is the integral type which is used to represent the enumerator values.

You can see the difference in this example:

#include <iostream>

enum class tiny : bool {
one, two
};

enum class bigger : long {
some, lots
};

int main(int argc, char *argv[])
{
std::cout << sizeof(tiny::one) << '\n'; //prints 1
std::cout << sizeof(bigger::some) << '\n'; //prints 8
}

In C++11 you can specify the underlying type of both scoped (i.e. class) and unscoped enums.

Deriving from an enum in C++

No this is not possible, even with enum classes.

Support for inheritance of enum classes was discussed for C++17, but was not incorporated into that standard.

Enum inheritance conflict

Given the following code:

#include <iostream>

class Base
{
public:
enum MyEnum1
{
A_VALUE = 1,
};

const int B_VALUE = 42;

int C_VALUE = -2;
};

class Derived : public Base
{
public:
enum MyEnum2
{
A_VALUE = 3,
};

const int B_VALUE = 180;

int C_VALUE = 99;

void test()
{
std::cout << A_VALUE << ' ';
std::cout << static_cast<const Base*>(this)->A_VALUE << ' ';

std::cout << B_VALUE << ' ';
std::cout << static_cast<const Base*>(this)->B_VALUE << ' ';

std::cout << C_VALUE << ' ';
std::cout << static_cast<const Base*>(this)->C_VALUE << std::endl;
}
};

int main()
{
Derived instance;
instance.test();
}

3 1 180 42 99 -2 will be printed.

This is because the identifier Derived::A_VALUE shadows that of Base::A_VALUE, and therefore an explicit cast to the base type must be made to access it. The same applies to other names defined at class scope, regardless of constness.

Here's a live example.

Why this doesn't yield a warning comes down to the implementation you're using, but there might be a variable shadowing warning that could cover this case. However, the standard does not have any concept of a warning, so there's no objective answer as to why your particular compiler isn't here (unless you send the implementers a message and ask, that is).

As others have said, strongly typed enums (C++11) do not have such an issue, as they must be accessed through the scope resolution operator ::, much like defining constants in a namespace.



Related Topics



Leave a reply



Submit