Holy cow, that's my USENET posting. Will have to ask my sysadmin to record the HN spike. I do find it funny reading postings here basically saying that, regardless of what Patrick Naughton said, his language is actually based on C++. Those language creators have some nerve! :-) Reminds me of the Kurt Vonnegut scene in Back to School.
Even back in the '90s, when I wrote that as a wee PhD student, it was clear that Java was derivative of Obj-C (among others) much more than C++.
EDIT: all the Newton references in that passage are because it was posted in comp.sys.newton.misc (IIRC).
None of them, unfortunately? (Unless I'm forgetting something.)
Of the languages created at Apple, Dylan was the most interesting one. Swift is practical in many ways, but it's not inspired or visionary.
Swift is basically a better C++ with decent Cocoa interop built-in. It's comparable to C# in originality... And that's not putting down either Apple or Microsoft -- it's simply the realities of creating a language at a large corporation with internal and external stakeholders.
I don't think 'originality' should be the goal of any language. Being novel for the sake of novelty inhibits effective communication, it doesn't enhance it.
Originality is a virtue if the language really has a better way of solving certain problems that people face. Even if it has merely a different way of solving certain problems, that may be very worthwhile, because the different way may in fact turn out to be better.
But novelty just for the sake of novelty... yeah, not so much.
I'm not sure how much Brad Cox[1] would like the characterization:
> Objective-C is an object-oriented mutant of C
But Java (the language) has little in common with C++ aside from the token-level commonality both share with B.
As for Java's interfaces, those (as "zak_mc_kraken" mentions) have strong ties to Objective-C's protocols, though I disagree with the subsequent statement of them being "a simplification of C++'s multiple inheritance". IMHO, they are far closer to C++'s class/function declarations.
I'd say Java had a similar influence as C++ did from Simula, introducing superficial similarities with C++ due to its dominance at the time[2], but incorporated more of the dynamics provided by Smalltalk-like languages (such as Objective-C). Note the use of "super" for calling parent methods and the lack of multiple inheritance in both.
2 - Fun bit of trivia: when Java hit the scene in the late 90's, you could globally replace the word "reference" with "pointer" and the documentation would read just the same. See section 2.2.9 of http://www.oracle.com/technetwork/java/simple-142616.html for a prime example.
I find a lot of similarities between Java and C++. Java is basically a subset of C++ with some sugar around. When I was learning Java, I just made a link between Java constructs and C++ constructs and that allowed me to learn Java in one day and start getting things done. Of course I took few years more to master Java, but that's another matter.
So Java "reference" is C++ pointer without asterisks and ->. All java methods are virtual. Java interface is full-abstract class without fields (in Java 8 even not so full-abstract). Multiple inheritance only with interfaces. No generics (I learned Java 1.4), one common ancestor Object, friendly GC releasing you from the pain of memory management.
Basically the only new concept is package. Otherwise it's stripped C++ with different runtime library.
> Java is basically a subset of C++ with some sugar around.
Not sure where you got that from... the notion of a class being a "reference type", which is the foundation of Java, doesn't even exist in C++. Every class type is a value type in C++.
Sure, it does. In C++, you can declare everything on the heap, then pass pointers by value. In Java, you declare everything on the heap (because you can't declare it anywhere else), then pass pointers by value (because you can't pass classes in any other way).
The only difference is that Java's subset also does not include pointer arithmetic, so this is actually a safe coding practice, because it allows for garbage collection to be performed.
Yes, C++ can emulate what Java is doing, but no, that's not what I'm saying. I'm saying C++ classes are not reference types, i.e., every class you define is always a value type, which is the exact opposite of Java. Obviously C++ also has pointers/references that could help you emulate Java, but that's beside the point. The point is that classes work differently in C++ and Java, and neither functionality is a subset of the other.
I suppose I'm not seeing the difference between Java's restriction of only using reference semantics, and C++'s option of using reference semantics. Since Java only provides reference semantics, while C++ allows both reference semantics and value semantics, this would make Java be a subset of C++, in this regard.
That was entirely intentional. Java adopted some C/C++ conventions that its designers knew were suboptimal, like == being reference, i.e. pointer, equality, switch statement with fallthrough etc. (even automatic number promotion, though I'm not sure it was clear to Java's designers that may not be such a good idea) precisely because they wanted C/C++ developers -- basically the entire market for Java developers at the time -- to be able to learn it quickly and make it feel familiar. Familiarity was purposefully chosen as one of the top design goals, as explained by James Gosling[1].
Today, these decisions would have been different, as C++ no longer reigns supreme. I find that Kotlin has completely adopted all of Java's core values, but modernized the specific syntax and semantics. Kotlin is what Java would have been if it had been designed today. The fact that Kotlin has made interoperation so seamless (you can switch any single Java class with a Kotlin file in an existing project -- IntelliJ would even automatically translate it for you) makes transitioning from Java to Kotlin (if you want) so smooth and gradual that it's a tru pleasure (even working on a mixed codebase).
Though, I think people are mixing together two different discussions in the article and thread: the internal design of the language, and the external consumption of the language. As a user of either language, where the internals can be considered as a black box, sure, they're both incredibly similar.
> I find a lot of similarities between Java and C++. Java is basically a subset of C++ with some sugar around.
I learned Java and C++ at the same time. And I had a hard time doing it because I believed Sun's marketing department that Java was a better C++. When I finally realized that was a classic bit of puffery, and that the marketing was simply trying to make Java look powerful by association with C++, I was able to make some progress.
I believe the similarities you find between Java and C++ are entirely intentional. But I respectfully disagree with:
> Java is basically a subset of C++ with some sugar around.
Here are a few reasons why:
* As you said, all Java classes inherit from a common type; java.lang.Object (Smalltalk).
* Inner classes automatically have a reference to the containing class (not in C++, though Java "nested classes"[1] behave similar to C++ structs/classes).
* java.lang.ClassLoader has no corresponding abstraction in C++.
* C++ has pass-by-reference semantics which is completely missing in Java.
* C++ supports destructors intrinsically.
* All definitions must exist within a type in Java. There is no concept of a "free standing" definition.
* Java provides meta-objects by way of java.lang.Class for all classes (not present in C++).
* Java does not support stack-based allocation except for built-in POD's.
> Java interface is full-abstract class without fields (in Java 8 even not so full-abstract). Multiple inheritance only with interfaces.
A Java interface has a distinct type within the type system, yes, and there exist meta-objects describing them generated as well. But until Java 8, interfaces had no behaviour and could only declare static fields.
> So Java "reference" is C++ pointer without asterisks and ->.
Pretty much.
As an aside, it has always cracked me up that a language touted as having no pointers has a "NullPointerException" class. (I am easily amused)
> * As you said, all Java classes inherit from a common type; java.lang.Object (Smalltalk).
You can limit yourself in C++ to inherit your objects from a common type. I believe that Qt did just that, for example. So this is a subset of C++.
> * Inner classes automatically have a reference to the containing class (not in C++, though Java "nested classes"[1] behave similar to C++ structs/classes).
That's a good example of simple sugar. Inner class just have pointer to the outer class and constructor with this parameter. Java compiler emits this code automatically. Yes, there's no such thing in C++, but it's very simple to emulate.
> * C++ has pass-by-reference semantics which is completely missing in Java.
> * C++ supports destructors intrinsically.
> * All definitions must exist within a type in Java. There is no concept of a "free standing" definition.
> * Java does not support stack-based allocation except for built-in POD's.
Yes, Java is subset of C++ in that regard. C++ has more features which were stripped out.
> * java.lang.ClassLoader has no corresponding abstraction in C++.
> * Java provides meta-objects by way of java.lang.Class for all classes (not present in C++).
Actually those systems could be emulated more or less in C++. Windows does have COM (and there are a lot of less known, but similar systems) which allows to dynamically load classes with virtual methods, etc. Qt implements (with some preprocessor magic) reflection for C++. But generally yes, C++ does not have any kind of runtime reflection (except dynamic_cast) and dynamic code loading, I agree here. What I want to point out is, that those features are provided by JVM. Java as a language does not have anything related to reflection or class loading. So probably it's not fair to compare Java + JVM to C++.
> As an aside, it has always cracked me up that a language touted as having no pointers has a "NullPointerException" class. (I am easily amused)
That's very unfortunate mess of terms. Pointers should be pointers, even if there's no pointer arithmetic in the language. Now we have pointers, references, pass-by-reference and beginners having hard time to understand what that even mean.
Your itemized explanations of what can be done in C++ only reinforces that the environments are quite different.
One of the wonderful things about C++[1] is that it can express just about anything which can be encoded in a program. GC, common base types, functional programming, imperative programming, object oriented programming, meta-programming, logic-based systems, dynamic module systems (a la Apache modules[2]), and a bunch more.
But that does not make a language such as Java a subset, unless your premise is that any language which can in some way be expressed in or embedded int C++ qualifies as a subset. If that's the case, then pretty much every language "is a subset of C++" (and yes, even Lisp[3]).
1 - Yes, I mean "wonderful things" as I have worked in C++ for many years. Still do when the problem calls for it.
Ditto. Strong types, bounds checking, and after Java 1.1, recursive nesting of program components.
More than Microsoft, I think Java killed Borland. Java had no IDE back in 95/96, but the compiler was free and it also ran on Linux, which Borland was late to adopt.
... then Anders went to work for Microsoft, and the rest is tragedy.
I'd argue that in the case of your first example, C++ is correct. Promoting int to double in this case does not bother me whatsoever. (In fact, mathematically, an integer is a real, though the reverse is not always true.
After thinking about it a bit, that also is well-typed in C. (You can argue that it shouldn't be allowed, but that's a different argument than that the language is not strongly-typed because of that feature.)
Exactly my experience - coming from C++, I never had to "learn" Java at all, and (at least until recently) there were only a handful of Java idioms that were unique to it that you had to grok. And this is exactly what you'd expect from a sensible pragmatic language design back then - take the dominant language in a domain (C++) and simplify it.
I think the stronger similarities came much later when generics were introduced. Both languages were then on a path of horrific type-nazism at that point. Strong static typing + a weak type system = rubbish. Sprinkle in design pattern-itis you have the mess both languages are currently in.
It's questionable what's better: simple type system without generics (Java 1.4, Go), something in between (Java 1.5) or something full-featured but hard to learn (Scala).
Scala pretends to solve this problem by "layering" code. Complex types are for libraries and users should use libraries. But IMO it never worked. Problems arising, "users" have to debug into library code and they have to deal with full-featured types anyway.
My only real wish in regard to Java 1.4 was that I would be able to implicitly cast Object to anything (like I can in Objective C). That would help to reduce type clutter a lot.
> Scala pretends to solve this problem by "layering" code.
From my perspective that's the large difference between Java and Scala. In Java, complexity leaks into the use-site (especially with Generics), in Scala it's possible to shield the user from that complexity.
Yes, I would agree with this. I was able to learn (not master) Java very quickly for Android development as I was familiar with C++, so it looks to me like a simplified C++ (isn't every language???) with some restrictions placed on it (inheritance etc.).
Not very convincing. Maybe Patrick Naughton was in love with Objective C but there is little of that left in Java.
Depending on which angle you look at, you could see Java's interfaces as a direct successor of Objective C's protocols or a simplification of C++' multiple inheritance.
If you were to believe James Gosling, it's clearly the latter that influenced Java's design. The fact that Naughton liked Objective C hasn't had much impact on what Java ended up looking like in 1995.
Having programmed many, many lines of C++, Java and Objective-C, I'd have to agree. Maybe parts of Java were influenced by Objective-C, but surely there is very, very little left of the philosophy behind how you write Objective-C code. In fact, I'd say there's almost no similarity whatsoever.
In terms of how you program, Java is a lot more like C++, minus half the language features that make C++ both powerful and dangerous. Obviously there are fundamental differences, but I think it's pretty clear that someone switching from C++ to Java would have a much easier time adjusting, then going from C++ to Objective-C.
Also, I find the qualification of Objective-C as a 'mutant of C' a bit off the mark. Yes, Objective-C is a superset of C, it's built on exactly the same foundation, but the end result is and how you use it is completely different in almost everything except the syntax of the pure C-constructs and fundamental types.
I'd put that more around 1997-8. Java 1.0 and 1.1 definitely felt a lot more like programming objective-c both in terms of the features available and the style the community developed in. Somewhere in the Java 1.2-1.5 things changed considerably. I agree that by then it felt way more like C++ than Objective-C.
The saddest thing is that Java never implemented support for Objective-C 'Categories' so Java programmers are forever doomed to write classes called StringUtil full of methods that really should be on the String class. After 20 years of Java programming this still annoys me.
1) You have no way of knowing that your category method isn't going to collide with another method. That method could be one of Apple's private ones, or it could be a method from a category used by another library you included in your app, or it could be even be from a category used in a jailbreak tweak. In all these cases, it's entirely possible that the colliding method doesn't have the same size arguments or return type as yours, in which case you are going to get extremely difficult to debug crashes. You also don't have guarantees around whose categories win.
2) As a class developer, you have no way of preventing categories from messing up internal guarantees of your class. Want it to be immutable? Too bad, some developer you've never talked to added methods in a category that require local state. Want to add and use a new private method? Too bad, that name is already taken by some random category, and now it looks like your code is breaking everything because it was just committed.
Prefixing category methods is a partial fix, but lots of folks aren't aware that they should do that.
Collisions are very very rare. In over 10 years of Objective-C development I have maybe seen it once. Also: clang got much better at detecting collisions at compile time (where possible).
That said: Swift extensions are safer because private categories cannot collide.
On the other hand, when you do have categories in a language and not the smartest people in the language's community, you do have real problems: You end up with conflicting definitions of homonymic methods because every one wants his own "toJson" crap. And everyone tries to monkey patch every other components. Ruby is plagued by this disease.
Haxe and Scala (and probably many others) have a nice solution to this problem. You can add "methods" to existing classes but only you can see them. You never really change the semantic of something that does not belong to you.
Ruby is hilarious because importing a library in the standard library (or importing a library that uses it) can break division: https://bugs.ruby-lang.org/issues/2121
To me, the worst thing about Java is the tooling and OS integration. Compare what it takes to invoke a node program with what it takes to invoke a Java program. Or what it takes to do basic file IO in either of those. It's crazy, and it will never get better. The best Java can do is wrap everything in a build system ("just add an exec compiler plugin, configure for your main class, and invoke mvn with special arguments!") or an IDE ("just create a run config through the following 20 step process...").
It's true that if you spend a lot of time in Java these things fade into the background, but these are exactly the things that shouldn't fade. You'll never "whip up a quick script" in Java because of these problems.
Java was never designed to "whip up a quick script". Today as in 1995 there are better alternatives to do that. Also Java was designed to abstract away from the underlying OS to provide "write once, run anywhere" so its "as designed" that OS integration is lacking.
Personally I think the tooling is the best part of Java. Having an IDE helps you build more robust software by providing far more context than a text editor ever could. The build systems have reached the point that its very easy to do the right thing to build robust software. Compared with what came before (make, imake, configure etc) the tools are much better.
Sure, node CAN be faster to get going. So what? Shell scripts are even faster to bootstrap than node. Will you switch over to doing everything in bash instead?
Also, yes, I whip up quick scripts in Java all the time, because sometimes it's the closest hammer to my particular nail. Your entire comment can be summed up as "I don't really understand Java, and I don't like it" which is not a terribly compelling argument.
Patrick Naughton... now there's a name I haven't heard in a long time. I went to Wikipedia to find out what happened to him after his arrest. No jail time, but he had to work for the FBI for free for a year.
Maybe true. I recently ported an Obj-C project containing 9000+ lines of code ( no GUI ) to Java and was quite surprised about how easy the Obj-C code was to read even though I knew nothing about it.
The naming of parameters in method calls was something I found a bit weird and overly verbose when I first used ObjC.
But I've come to appreciate that it can greatly improve readability when trawling through unfamiliar code bases, and thankfully it's a feature Apple have carried across to Swift.
Now days I often wish Java had external parameter names, too!
One of my fave obj-c features (which comes from smalltalk, I am told), and I'm surprised more languages don't do it. Aids code readability immensely, and basically eliminates an entire class of bug (of accidentally transposing two params of the same type).
Most people tend to react to it really negatively at first encounter though.
I had done the opposite for a hobby scheme-like interpreter found in github from Java into ObjC, but finding various difficulties doing the same into Swift at the early days of it.
Converting that piece of Java codes into ObjC was easy and straightforward because it was basically just some Foundation classes, e.g. NSString, NSArray, NSDictionary and NSNumber.
Wait... C# was strongly influenced by Java... by law of transitive properties that means C# was strongly influenced by Objective-C..... Nooooooooooooooooooooooooooooooooooooo.
That's like the opposite of finding out that Sweden named New York
That is pretty much the same way that I remember it as well. The interesting dichotomy is that the NeXT 'cabal' as it were, primarily, the code/library developers as was I, and James was primarily language design. But the group was small enough that everyone had an opinion, and it often came up "well Objective C does it this way..." or "C++ does it this way ...". James was always a minimalist and Bill Joy (who was in Aspen working on the 'self' language) was always pushing the edge of what you could express in a language.
Objective-C was strongly influenced by smalltalk. I think Java is more influenced by smalltalk than by Objective-C. The whole concept of compilation toward bytecode that may be interpreted or compiled to native is very similar to smalltalk. I think the influence of objective-C and C++ was mainly to avoid reproducing mistakes, in particular the tricky syntax. The syntax of smalltalk is very clean and simple which is not the case of C++ or objective-C.
Java the language is more like Simula than Smalltalk. But yes, the JVM/runtime is vaguely Smalltalkish, and this is no accident given that many of the key contributors came from Self and Smalltalk lineages.
An interesting tidbit on two unused keywords from the 1.0 specification [1]:
"The keywords const and goto are reserved by Java, even though they are not currently used in Java. This may allow a Java compiler to produce better error messages if these C++ keywords incorrectly appear in Java programs."
I remember when I moved from obj-c to java (as WebObjects made the same transition) and being amazed at just how bad the java standard libraries where compared to the obj-c foundation and other nextstep libraries. The obj-c libraries were so nice and clean and focused.
Funny to see the 'oak' name reused - it's now an Apache project for a jcr backend.
The difference between WebObjects as a obj-c program to java program was just heart breaking. You could further see the pain of transition in the Java bridge for Cocoa. It really showed the mismatch between obj-c and java.
Even back in the '90s, when I wrote that as a wee PhD student, it was clear that Java was derivative of Obj-C (among others) much more than C++.
EDIT: all the Newton references in that passage are because it was posted in comp.sys.newton.misc (IIRC).