On 29/04/2013 19:24, Steven D'Aprano wrote:
On 30/04/13 03:01, Guido van Rossum wrote:

Oh dear, this is actually a mess. I don't want MoreColor.red and
Color.red to be distinct objects, but then the isinstance() checks
will become confusing. If we don't override isinstance(), we'll
get

not isinstance(Color.red, MoreColor) isinstance(MoreColor.yellow,
Color)

This would be pretty backwards.

Why is that backwards? MoreColor is a subclass of Color, so instances
of MoreColor are instances of Color, but instances of Color are not
instances of MoreColor. That's normal behaviour for subclasses. (All
cats are mammals, but not all mammals are cats.)

Let's say that Color is red, green, or blue.

Let's also say that MoreColor is superset of Color, in other words, any
of Color, plus cyan, magenta, or yellow.

Red is a Color and a MoreColor (member of Color and MoreColor).

Yellow is a MoreColor, but not a Color (member of MoreColor but not
Color).

That's the opposite of the rules of inheritance.

The only "funny" thing about this is that enumeration values of a
Enum are only instances of that Enum if they are declared inside that
Enum, and as far as I'm concerned that's not especially funny at all.
So:

Color declares red, so Color.red is a Color.

MoreColor does not declare red, it merely inherits it from Color, so
MoreColor.red is Color.red which is not a MoreColor.


This leads to a simple rule:

Enum values are either instances of the enum they are defined in, or
instances of the parent class they are inherited from.

If the user doesn't like that, they're free to not subclass Enums
:-)



I Ggoogled "enum subclassing" and found this StackOverflow article
explaining why you can't subclass enums in Java:
http://stackoverflow.com/questions/4604978/subclassing-an-enum
which refers to this more elaborate answer:
http://stackoverflow.com/questions/3427947/enumeration-inheritence-in-java/3428050#3428050


The first link says:

"And generally, a proper subclass is a specialization of its
superclass."

and gives the Liskov Substitution Principle as the reason for
prohibiting subclassing. LSP is a very useful principle, but it is
not the only model for subclassing. That's why it's called a
*principle* and not the Liskov Substitution *Law*.

(Yes, I stole that from Raymond Hettinger's talk on subclassing at
PyCon.)

I think that the ability to extend enums with new ones, without
duplicating code, is more important for enums than satisfying LSP.
The common use-cases for enums do not lend itself to subtyping in the
Liskov sense.

E.g. if I have a function that expects a Color red/blue/green enum,
and I subclass it to give MoreColor yellow, I can't expect the
function to suddenly recognise yellow. So I'm not going to use
subclassing in this case, because it can't work.

But I will use subclassing to reuse values: if I have a function that
expects red/blue/green/yellow, and red/blue/green are already defined
in Color, I'll want to reuse them rather than duplicate them. Hence I
will subclass Color specifically to extend it, not to specialise it.

On the other hand, a function that expects MoreColor should also accept
Color, which is a subset.


The second link quotes:

"For the most part, extensibility of enums turns out to be a bad
idea. It is confusing that elements of an extension type are
instances of the base type and not vice versa."

Confusing for who, and why?

You're going to confuse *somebody* no matter what you do. Either:

- confuse people who try to subclass enums, and can't; or

- confuse people who try to subclass enums, and can, but then get
confused by the result.

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to