3 ms·
- True; I was just considering the mainstream languages. Yes, if you include Smalltalk, LISP, I'm sure there are better alternatives to learn specific concepts.
by wladimir 16y ago
- True; I was just considering the mainstream languages. Yes, if you include Smalltalk, LISP, I'm sure there are better alternatives to learn specific concepts. But Java is used a lot in practice, and looks a lot like other languages used in practice (C++, ObjC, C#, and friends), which in my experience makes students more enthusiastic.
- I agree the "generics" are complex and overly verbose. They almost look like the C++ templated types, which I would go around with a 10 foot pole if I wanted to learn someone programming... IMO, pre-1.5 Java was best for learning.
- Yes, a lot of the verbosity is pointless, I think it helps for learning to specifically mention everything and be a bit repetitive. Other languages luckily allow leaving the obvious stuff out.
- bad_user 16y agoRuby and Python are also mainstream, and both provide saner OOP. C++ templates at least have a purpose and provide extra benefits (e.g. performance, compile-time computations for pre-caching). In Java generics are practically implicit type-casts and nothing else. About verbosity ... clear conventions are a lot more effective for readability and learning. In a dynamic language like Ruby / Python, if you don't know what an object's type is or what it does, the fix is as easy as ... obj = don_t_know_the_return_type() # doing lots of stuff import pdb pdb.set_trace() That opens up a Python debugging console at the current point of execution, and you can inspect "obj" for its type / members and also modify its state. Also, if you're using "ipdb" instead of pdb then you've also got auto-completion on <TAB> (e.g. Intellisense). You can do something similar in Ruby, and in Smalltalk the whole application is active while you're typing in the IDE. There, problem solved.
- uriel 16y ago> Ruby and Python are also mainstream, and both provide saner OOP. For various other reasons I prefer Python to Java (or Ruby), but there is one thing that Java got right and Python totally messed up: avoiding the disaster that is multiple inheritance. Of course a much better option is to completely do away with inheritance like Go has done (plus Go combines some of the advantages of Python's 'duck typing' with the static type checking of Java's interfaces).
- bad_user 16y agoFrom where did you get the idea that multiple-inheritance (in general) is a disaster? Multiple-inheritance is only a disaster when the rules aren't clear on ... (a) what you're inheriting (b) what you're overriding (c) what happens when you try calling super:: Otherwise, inheritance is really useful, and Python scores pretty good on all the above points. Also, GO doesn't have "duck typing". That's called "structural typing" and it is a lot more limited than dynamic typing. GO is not really object-oriented either.
- moopark 16y agoHow do you define (and enforce) those rules? My general position when writing library code is that none of my classes should be subclassed. The very few classes that may be subclassed are documented as such, and the methods that may be overridden are explicitly documented, as well as what behavior is required from the subclass when overriding those methods. The invariants of complex inheritance hierarchies are very hard to understand. What happens if the superclass method isn't called? What happens if one of those methods is called, but another isn't, and the object is placed into an indeterminate state? What enforces that your subclass -- and all other subclasses -- will conform to these often complex and difficult to describe invariants? This is very similar to multi-threading with mutable vs. immutable data. By making your data immutable, you grossly simplify the understanding of your system's behavior.
- bad_user 16y agoWhy do you need to enforce rules, other than documenting the classes/methods defined? What happens if the superclass method isn't called Shit doesn't work or it breaks, then the person who sub-classed needs to fix it. Sometimes it also means your class is leaking encapsulation. This also happens with plain aggregation/composition btw. It also happens with data-immutability (which has nothing to do with inheritance, as your object can be immutable and extend a dozen classes).
- moopark 16y ago
- moopark 16y agoThere, problem solved. The problem isn't solved. You now know what the type is for that particular moment. What you don't know are the invariants of the don_t_know_the_return_type() function. What types/subtypes is can return, whether it can return None, what exceptions it can throw, and whether those will change in the future. That information can only come from a type system and/or documentation. Simply reading the implementation only tells you the current state of the system, not the rules that will govern future iterations of it. The more invariants that can be expressed concisely by the language itself and enforced by the compiler, the less work is left to the user of the function to review documentation/implementation. This is one large reason why well-designed advanced type systems are so valuable -- you can express complex invariants using them, and then let the compiler enforce those invariants.
- bad_user 16y agoFirst, even in Java you don't know the return type / invariants ... int n = func_that_returns_positive_even_number() What you need is to document the thing: def func_that_returns_positive_even_number(): """Returns positive even number.""" This comment will be available when typing "help(func_that_returns_positive_even_number)" in the Python console btw. Or if you're paranoid and that function can totally break your code: n = func_that_returns_positive_even_number() assert isinstance(n, int) and n % 2 == 0 and n >= 0 Or to make extra sure this will hold in the future (i.e. protecting from code-changes done by other people) ... import unittest class TestMyFunc(unittest.TestCase): def test_is_positive_and_even(self): n = func_that_returns_positive_even_number() self.assertTrue( n % 2 == 0 and n >= 0 )
- moopark 16y agoFirst, even in Java you don't know the return type / invariants ... This is a classic type system straw man. The language doesn't support encoding integer ranges in the type system, ergo, the type system is not ever a significant advantage and all invariants must be documented. You fool! What you need is to document the thing: Some invariants require further documentation. The more you can express concisely in code via the type system, the more time you and your API clients save in both development and maintenance. More succinctly: By expressing them in code you let the compiler automate the work of enforcing them. Or if you're paranoid and that function can totally break your code: An assert doesn't "protect" your code from future changes (better phrasing would be: make your code adaptable to change, loosely coupled with its dependencies as to allow iteration of your code and its dependencies independently). An assert simply causes your code to fail in an obvious way. It's still up to you to track them down (at runtime) and figure out where you went wrong.
- regularfry 16y ago> I think it helps for learning to specifically mention everything and be a bit repetitive. That's right at the bottom level of the Dreyfus model of skills acquisition. One may be able to draw inference from this to the apparent profusion of useless Java coders, but that's further than I'd really want to go. Once you've stepped off that bottom rung, however, it's all noise and just gets in the way.