[Alex]
> Of course, it's possible that some such wrappers are coded much
> more tighter &c, so that in fact some roundabout A -> X1 -> X2 -> C
> would actually be better performing than either A -> B -> C or A -> Z
> -> C, but using one of the shortest available paths appears to be a
> reasonable heuristic for what, if one "assumes away" any degradation,
> is after all a minor issue.

I would think that the main reason for preferring the shortest path is
the two degenerate cases, A->A (no adaptation necessary) and A->C (a
direct adapter is available). These are always preferable over longer
possibilities.

> Demanding that the set of paths of minimal available length has exactly
> one element is strange, though,

I think you're over-emphasizing this point (in several messages);
somehow you sound a bit like you're triumphant over having found a bug
in your opponent's reasoning.

[...]
> So, yes, I'd _also_ love to have two grades of inheritance, one of the
> "total commitment" kind (implying transitivity and whatever), and one
> more earthly a la ``I'm just doing some convenient reuse, leave me
> alone''.

I'll bet that the list of situations where occasionally you wish you
had more control over Python's behavior is a lot longer than that, and
I think that if we started implementing that wish list (or anybody's
wish list), we would soon find that we had destroyed Python's charming
simplicity.

My personal POV here: even when you break Liskov in subtle ways, there
are lots of situations where assuming substitutability has no ill
effects, so I'm happy to pretend that a subclass is always a subtype
of all of its base classes, (and their base classes, etc.). If it
isn't, you can always provide an explicit adapter to rectify things.

As an example where a subclass that isn't a subtype can be used
successfully, consider a base class that defines addition to instances
of the same class. Now consider a subclass that overrides addition to
only handle addition to instances of that same subclass; this is a
Liskov violation. Now suppose the base class also has a factory
function that produces new instances, and the subclass overrides this
to produce new instances of the subclass. Then a function designed to
take an instance of the base class and return the sum of the instances
produced by calling the factory method a few times will work perfectly
with a subclass instance as argument. Concrete:

class B:
    def add(self, other: B) -> B: ...
    def factory(self) -> B: ...

class C(B):
    def add(self, other: C) -> C: ... # "other: C" violates Liskov
    def factory(self) -> C: ...

def foo(x: B) -> B:
    x1 = x.factory()
    x2 = x.factory()
    return x1.add(x2)

This code works fine in today's python if one leaves the type
declarations out. I don't think anybody is served by forbidding it.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
_______________________________________________
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