There is no valid use case I've ever seen where inheritance was better than composition (that does not mean a use case does not exist, but evidence is mounting against it). I would say it's used because every language made a poor decision by building that in as the way to encapsulate reusable logic. i.e., a mistake.
Some APIs may expose themselves as requiring you extend a base class, and in that case you might as well do what the library author said. But overall? Yes, some things can work well with inheritance (eg. classical UI frameworks), but these are often equally good with a composition based API.
One job I was at I added a lint rule to flag `extends` as an error. You would need to add a comment to justify why you were using inheritance - it went over more favourably than I expected. I think I would suggest this for any new projects using a language that supports inheritance - discourage it with automation, but allow really good reasoning to prevail in review. It is the worse solution at least 99% of the time because it requires you predict a future that is painful to change.
Some APIs may expose themselves as requiring you extend a base class, and in that case you might as well do what the library author said. But overall? Yes, some things can work well with inheritance (eg. classical UI frameworks), but these are often equally good with a composition based API.
One job I was at I added a lint rule to flag `extends` as an error. You would need to add a comment to justify why you were using inheritance - it went over more favourably than I expected. I think I would suggest this for any new projects using a language that supports inheritance - discourage it with automation, but allow really good reasoning to prevail in review. It is the worse solution at least 99% of the time because it requires you predict a future that is painful to change.