This answer is going to be unconventional but that's probably what you are looking for since plenty of more academic answers exist.
At the end of the day, Factuser
is dispatching Factorial2
methods. It literally needs to access that part in memory where they are stored. We can say Factuser
depends on Factorial2
at runtime.
Had you implemented Factuser
with no injection via the constructor, it would have had to mention the name of Factorial2
in order to instantiate it and use it (and the other variant as well). In other words, Factuser
would have depended on Factorial2
in the source code as well. In such case we say the source code dependencies flow in the same direction as the runtime dependencies.
Instead, you made both Factuser
and Factorial2
mention the name of a common interface, IFact
, which they both have to look up in their source code. What this achieves is decoupling Factuser
from a specific implementation of IFact
, and that's good. However, it doesn't mean Factorial2
is now magically depending on Factuser
. Indeed, programming to an interface on itself is not inverting anything, it's just adding an indirection.
The inversion happens if you split the code in different modules and you decide that the IFact
interface is owned by the user module. This module doesn't need to mention any name from the outside world, so it doesn't depend on anything. On the other hand, the module containing Factorial2
needs to import IFact
from the user module and now depends on it. To sum it up: the implementations module depends on the user module, which is the opposite of the runtime dependency, we have our inversion.