Yes, this is obviously bad; that's because your type hierarchy is neccessarily public API. If your API exposes a UserManagementService, I can use it as a DatabaseConnectionService object. That means that your choice to have UMS extend DCS is locked in - if you ever change that, any code that uses your UMS may then fail. You can try to solve this in documentation:
/**
* Lets you query information about, and perform operations on,
* the storage of users allowed on this service.
*
* IMPORTANT NOTE: Even though this class extends DatabaseConnectionService,
* this is <em>not guaranteed</em> by this implementation,
* so do not rely on this!
*/
public class UserManagementService extends DatabaseConnectionService {
...
}
But surely you can see that this is pretty suboptimal and 'ugly' (hard to maintain - you can't test that other code you have no control over actually heeds your warning here).
It also applies in reverse: If ever DCS adds something that just makes no sense for a UMS to have, then your UMS is, all of a sudden, broken and exposes crazy stuff that makes no sense and causes many questions or worse.
Contrast this to declaring that a Student is some kind of Person: That's inherently true; that is not merely a convenient implementation detail. If the country at large gains some sort of servicenumber feature and you extend the Person class to support this, then Students all of a sudden also gain this servicenumber thing. But that's good: Students ARE persons, after all.
So, how do you fix it?
Easy. Don't extend DCS. Create a field of type DCS, and if there are a bunch of methods that DCS has that you want UMS to also have, write em out. Their implementations can be very simple oneliners:
public int count() {
return dataConService.count();
}
// and a lot more of this, if really needed.
Common retort to this logic: But I control it all and I don't foresee new features ever being added!
Well, okay, but understand that single-person throwaway projects are a very bad basis to talk 'style guides and code cleanliness' - it's just you, hacking away for a weekend, write it however you like, you'll be fine.
Style guides and approaches to coding become useful when a team of 50 programmers program an application that is to survive and be in the business for over a decade, with programmers leaving and new programmers joining the team, and 5 years after the project is started, features you didn't even think of yet need to be added because of customer demand.
With that in mind, understand that code bases become gigantic and it'll be very hard to safely change things and train new programmers to become familiar with it. One extremely useful way to make that a little easier is to aggressively modularize things: Anytime you can draw the entire sourcecode base on a whiteboard (which will be huge), but then draw a smallish circle around a tiny part of it and go: This stuff can be understood all by itself, tested by itself, and developed on without completely understanding all the other source code - that's good. That's what you want.
"UMS currently extends DCS but don't rely on that" is exactly the kind of thing that makes drawing that tiny circle more complicated, which is why it's not a good idea to do it.