Ignore the tree. Suppose you have _seals_, who are plausibly 'barkers' in the same sense as dogs. Take an array Dog[] and pass it to a function that accepts Barker[]. It seems reasonable to take a Barker from the array, nice and safe. But suppose we try to put a Seal into the array, that's not fine: it's a Dog[].
Famously java got this wrong, but runtime checks (somewhat) stop that being a disaster.
But let's say you have Admin and EndUser that both implement the User class. You would think you could use a []EndUser on a function that takes a []User. Because you can use a EndUser when you need a User.
Except you can't because of mutability. In Scala for example, ListBuffer is invarient (because you could append the wrong type) however the immutable List is covarient so you can call a function that takes a List[User] and pass it a List[EndUser].