Why [1, 2, 3] is not a Vector{Number}?

Wow, I explained the logical issue with subtyping concrete types a lot better back in 2014: Why is it impossible to subtype a struct? - #3 by StefanKarpinski. Of course, the issue was much fresher in my mind back then. Here’s what I wrote:

While there are a number of practical reasons to disallow subtyping of concrete types, I think they all stem from the basic fact that subtyping a concrete type is logically unsound. A type can only be instantiated if it is completely specified, and it only makes sense to subtype something if it is incompletely specified. Thus, a type should either be abstract or concrete but not both. What object-oriented languages that allow the same type to be both instantiated and subtyped are really doing is using the same name for two different things: a concrete type that can be instantiated and an abstract type that can be subtyped. Problems ensue since there’s no way to express which you mean. You end up with attempts to resolve this confusion like the “final” keyword and recommendations against ever subtyping classes that weren’t intended to be abstract. But wouldn’t it be better not to conflate the two things in the first place?

The point where OOP languages disagree with this analysis is that they consider it fine to subtype something that is completely specified in order to modify its behavior, rather than merely to finish specifying an incompletely specified abstraction. This highlights two very distinct kinds of subtyping:

  1. Subtyping to complete a partially implemented abstraction;
  2. Subtyping to modify an already-complete, concrete implementation.

We basically take the position that the first kind of subtyping is ok but the second kind is not and is therefore disallowed, whereas standard OOP languages allow both. One of the main ways that people want to “modify” an already-complete, concrete implementation in class-based OOP languages is by adding new methods to them, which is something that doesn’t require subtyping at all in Julia because methods are added externally. So one of the major reasons to need the second kind of subtyping is absent in Julia, making it far easier to completely forgo it.

17 Likes