So the question basically drills down to why one should use composition instead of inheritance. Most OOP languages only allow inheriting from a single class, and that alone is reason enough to prefer composition in most cases. It's one of the reasons I'm particularly fond of traits/modules.
I don't really know of any OOP language that doesn't have some concept of multiple defined interfaces (eg HasPlayers, HasHomeCity), which is really what you'd want in this case rather than traits or modules.
Java just might become the Fortran of the 21st century -- embarrassingly out of date, but due to vast amounts of legacy code, impossible to get rid of.
Edit: I misread you and I interpreted that you meant Java was already a legacy and out of date language. So my answer is a little out of place, although I don't think there's any harm in keeping it here.
I disagree. I know that Java gets a lot of hate, here and in a lot of places, and I won't deny that a lot of it is indeed very well deserved, but it's far from being a "legacy" language. A quite large amount of software is being developed nowadays in Java, and in many cases, there are good reasons for that.
About the "embarrassingly out of date" part, I also think that's too exagerated. Java was never intended to be a cutting edge language, but a reliable set of well-proven techniques. Java doesn't want to be Haskell, doesn't want to be Ruby, and doesn't want to be Lisp; and explicitly so. Java has modest design goals; but it does fulfill them, which is why it's such a successful language even if it's not suitable for a lot of projects that you, myself or the rest of HN visitors may be interested in. But, on top of that, Java actually tries to incorporate functionality that has been successfully proven in different, and more innovative, lenguages (at an admittedly slow pace). Conservative, yes; out of date, I don't think so.
I'm not really fond of Java, and if I had to choose, I think there's probably no project for which I'd take it instead of some other language; however, its virtues are there.
> I know that Java gets a lot of hate, here and in a lot of places, and I won't deny that a lot of it is indeed very well deserved, but it's far from being a "legacy" language.
No, not yet, and I understand that you've edited your reply. I'm only saying that over time Java has more and more properties that are (a) out of date and (b) impractical to change because of legacy considerations.
The last time the Java developers made a major, code-invalidating change was when they decided that their event processing method needed to be replaced. It was a beneficial change, but a painful transition including a lot of "deprecated and to be removed" notifications and rewriting of existing code.
Since that time, no further major changes have been made that would invalidate existing code, which is as it should be, but this means Java inevitably becomes more and more out-of-date as time passes.
I emphasize that I write a lot of Java -- most of my best-known current programs are in Java, just because it will run on most platforms without any fuss.
> ... it's far from being a "legacy" language.
Like growing old, this doesn't happen all at once. :)
> Fortran is still evolving (albeit even more slowly than Java) and still used for new projects.
If it weren't for the fact that there is a huge trove of valuable legacy Fortran code, if Fortran were introduced today as a new language with no archive of existing Fortran programs, on its intrinsic merits it would be laughed off the stage. On that thought experiment's basis, Fortran continues to exist in order to support legacy code.
There are systems present in society of very high value that require Fortran to remain available, and some of them have famously undertaken to replace their Fortran code base at very high cost, and failed. So we have Fortran, and will continue to have Fortran, simply because of the very ambitious projects that were written in Fortran that we still need.
Yes, as somebody paying the bills mostly through Java, I can affirm that Java is the new COBOL.
While compensating for the excess of C++, too many good ideas went out the window, and we're left with something that extends COBOL by letting our copybooks, er, beans, have multiple instances, and letting out procedures, er, methods, have parameters, local variables and explicit return values.
There's a few other things Java does a bit better than COBOL, but it's used just like "COBOL with separate compilation" in standard "enterprise" practice.
Class invariant?
Closures?
Immutability?
Fuggedaboudit.
On the bright side, other languages are starting to highjack the JVM.
Composition making more sense is exactly why you'd use an interface, as the function inside the class depends on the internal implementation of how you'd store the players most efficiently while still giving a common method to access them. If you used a trait it would lock in the list implementation across all types that HadPlayers etc.
Yep. Team HAS-A list of players, not team IS-A list of players.
While we're at it, "List <? extends Player>" might be a better type for the roster, since it allows players to be subclassed and still fit into the list.