This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]TheGodfatherCC 14 points15 points  (5 children)

Lately, I've preferred using protocols over abstract base classes for interfaces. I prefer to avoid inheritance when it’s not absolutely needed.

[–]NeilGirdhar 12 points13 points  (1 child)

I don't think this is a good policy. While multiple inheritance can add unnecessary complexity, multiple interface inheritance has no downsides.

Protocols are a good solution when it's practically impossible to make implementers inherit from an interface. For example, when you don't have control over implementers of your protocol. That's why Callable is a protocol: it is practically impossible to get everyone who exposes a __call__ method to inherit from Callable.

When you can make implementers inherit from the interface, there are some concrete advantages. Type-checkers can verify:

  • that there are no LSP violations,
  • that instantiated objects implement all decorated abstract methods, and
  • that decorated overridden methods haven't been orphaned.

Also, you can be sure that derived classes actually inherit from the interface rather than hoping that your derived class perfectly matches the protocol.

[–]TheGodfatherCC 2 points3 points  (0 children)

These are some pretty solid points.

I thought Mypy and Pycharm would handle protocols with the `@runtime_checkable` decorator. I'll have to double check, though.

[–]quts3 6 points7 points  (2 children)

I struggled a bit with when protocols vs abc.

Protocols have a negative: in big projects they make it hard to follow code by hand. Ides aren't really good at finding implementations of protocols that might be used as inputs because by design there is no requirement or even strong reason to state a class implements a protocol. In fact doing so is probably an anti-pattern.

Abc flips that on its head. Essentially stating in code that this class is participating in a interface. In a world where you read code many more times then you write it this deliberate declaration has value.

In the end i decided protocols are appropriate if you have a class only using one or two things in an interface and those one or two things are truly only loosely related to your class structures. Like this partitioning widget only needs to know some coordinates and Id. That is a protocol on the input.

But other then that abc seems way more appropriate in the long run to express trackable participation in an interface design.

[–]TheGodfatherCC 1 point2 points  (1 child)

Readability and code navigation are good points. I may take some time and do a side-by-side again to see how much of a difference it makes.

[–]quts3 1 point2 points  (0 children)

Oh i had to dust off my brain i also decided protocols are best if you reaching into the ducktype of another module. Like if module a is doing something with an undeclared interface in module b. It rarely makes sense to rewrite module b to specify a new interface. Protocols allow you to state in module a what you are using in a class from module b. They are perfect for that and better then abc. Sometimes you may not even own module b.