You can do TCO in OOP languages just fine, because it's perfectly possible to have non-virtual functions in OOP languages. But even with virtual method dispatch you can do a tail call (by doing a function call that discards the old stack frame, that is, not by compiling the code to a loop), if you're using the right calling convention. Not that that's necessarily an optimization.