<hr><b>2004/03/11 12:27 EST (via web):</b><br> Critique of Eckel's mischaracterization of generics is here : http://www.theserverside.com/news/thread.tss?thread_id=24445#113713 It sounds to me like your disappointed that Sun's implementation of generics took a 'directing' attitude, while you would rather see an 'enabling' implementation. It doesn't seem right to expect that kind of change in direction from Sun. Java has always been about directing. It seems like it took this long to add generics to the language simply because Sun couldn't find a way to add them without a total change of philosophy. On the issue of Interfaces, I think your putting too much stock in the technical issues. Programming is performed by people. No matter how little an interface means to a computer, when a human being reads the code they infer a contract when they see an interface. These inferences may not be perfect, but their quick and powerful. I disagree that interfaces should be defined by how the computer thinks of them. Computer languages are meant as an intermediary between us and the computers. So as long as human understanding doesn't directly contradict the computer's interpretation, the human interpretation should always take precedence when defining the rules of a language. Bryan When I first read the article I thought that he must be wrong, that it was an old article. But when I tried compiling the code, I realized to my dismay that they really had implemented generics like that. I can't believe it. One common way to reuse with generics is to write utility methods/classes that operate on some types that have some common methods. Unfortunately implementing generics this way requires you to modify the classes so that they all implement some interface--try doing that with some java.* packages :( I would think that latent typing could still be acheived though erasure & syntax sugar by the compiler. There would still be the reflection problem--but at least usability would be greatly improved. Javadoc could even automatically a list of method signatures the type must have. <hr><b>2004/03/11 14:43 EST (via web):</b><br> C++ not so fly either Bruce is impressed with the way things work in C++ but maybe without realizing that it comes at the price of not having separate compilation anymore (at least unless you add trickery like concept casts, which introduce interfaces through the back door). Peter <hr><b>2004/03/11 16:37 EST (via web):</b><br> "What is Latent Typing?" Such a good question - the closest we get to an answer is "Latent typing simply makes the interfaces implicit". "Latent type" is usually referred to as an implicit interface - which makes the relationship to explicit interfaces obvious. <hr><b>2004/03/11 17:10 EST (via web):</b><br> Implicit interfaces are what the ENTIRE COMPUTING INDUSTRY should be running away from AS FAST AS HUMANLY POSSIBLE. We should DOCUMENT our interfaces, and the first step to documenting something is surely naming it meaningfully. It's not very practical to document tons of things if none of them are named meaningfully. This topic makes me very angry. <hr><b>2004/03/11 17:12 EST (via web):</b><br> Clarification to my last post: Obviously, as the example at the start of this blog post clearly showed, method names are not enough for disambiguation. We must have fully-qualified type names, too, for full disambiguation. <hr> It makes you angry because you believe you know the one true answer: that the only correct way to do things is to be as restrictive as possible. Have you ever tried using a programming language that wasn't as restrictive? With reflection, Java can be much more flexible, but if you only use restrictive techniques, you won't be able to think about how to do this and the kinds of applications you can create will be limited. kind Having done plenty of programming in both Java and Python, I find that I like Java interfaces. On a project where I can edit both the interface and all the implementations with a nice refactoring editor like IntelliJ, the interface serves simply as error-checked documentation - it's not restrictive at all to say what you mean with an interface when you can modify it at will. The only real problem with Java is that you can't retroactively declare your own interface on someone else's class. Latent types are one solution, but not the only one available if Sun is changing the language anyway. In the meantime, I make do with adapter classes. (And unless the method names line up exactly, you'd have to write an adapter class anyway!) Although you can document a latent type in Python, the compiler and editor don't do any error-checking so the documentation can easily go out of date. It's not for nothing that there are proposals to add explicitly declared interfaces to Python, particularly for Zope, which is a pretty good example of what happens in Python when the codebase gets above a certain size. (I still like Python's terseness and dislike Java's verbosity. But it's no longer a burning issue since I stopped using emacs.) (The first paragraph was written by someone else. What a lousy UI.) <hr><b>2004/03/12 03:37 EST (via web):</b><br> Latent typing is all goodness unless you're developing in a component-based language. A component-based language allows you to compile code at different times and allow those components to call one another. For example, imagine a 3rd party built a component with a callee method which took a latently typed object reference as a parameter. Suppose this callee method performed 3 operations on that object reference. Then suppose you built another component containing the caller. Generally, the caller will have been developed using unit tests to prove the code worked - all is fine at this point. Now suppose the 3rd party which developed the callee component altered it's implementation by calling another method on the object reference. Supposedly this is still backward compatible - but the caller could have passed any class into the callee which does not define the new method. A supposedly backward compatible component is no longer backward compatible primarily because latent typing has no contract between caller and callee. In summary, latent typing breaks component-based development by eschewing contracts. -- RichB <hr><b>2004/03/12 08:08 EST (via web):</b><br> I agree that the ability to retroactively declare your own interface on someone else's class is what is needed in Java to have the flexibility of latent typing without the inconvenients. See http://www.mindview.net/WebLog/wiki-0050 for an example of how **abstract interfaces** make that possible with <a href="http://nice.sf.net">Nice</a>. -- Daniel Bonniot http://www.jroller.com/page/dbr Semantics of interface is given by application usage. Whole premise of using interface is to define semantic of usage in aplication and it is expected that actual implementor follows sematic of implementing interface. From application development point of view you usually use interface and you have very well defined semantics for that interface in your application context. Implementor doesn't have semantics but has functionality appropriate to the interface sematics (in ideal world) :-) My 0.02 cents Igor Cunko <hr><b>2004/03/12 10:02 EST (via web):</b><br> About the "directing" vs. "enabling" approach, you wrote: "Both approaches are reasonable and neither is wrong. I have been in both situations; for example, trying to prevent interns from ignoring or even actively circumventing coding style guidelines (where more "direction" was required), and on the other hand being frustrated by the loss of productivity that comes from being forced to conform to constraints that I wouldn't have violated anyway [...]". It is interesting that you justified the "directing" approach with an example about directing others, and the "enabling" approach with an example about enabling yourself. Don't take this as a negative critique - I did the same when I tried to come up with examples of directing/enabling. I tend to think that *others* should be directed, and *I* should be enabled. I worked for teams whose job was developing software methodologies and the relative supporting tools for the rest of their Company. Except that, of course, they flat-out refused to apply the (directing, strict) methodologies that they were developing to their own methodology-building project. To me, that shows how much in software development is about our own relationships and fears. We still have an awful lot to learn from sociology and antropology - and maybe, oriental philosophies. Paolo Perrotta Bologna, Italy whoops, sorry if my last sentence came out "shouting"... I can't find out how to edit this Wiki to remove the bold formatting. how does this work? - Paolo In the following excerpt of an interview with the creator of C# (which has a similar generics implementation to Java) Anders talks about the differences between the C# way (and by implication Java) of type checking generics at compile time which he claims is strong in contrast to C++ which he implies does not do type checking of generics at compile time. I think this is false but I'll see if Bruce will comment on this. <p> <h2>"Comparing C# Generics to C++ Templates</h2> <p> <b>Bruce Eckel</b>: How do C# generics compare with C++ templates? <p> <b>Anders Hejlsberg</b>: To me the best way to understand the distinction between C# generics and C++ templates is this: C# generics are really just like classes, except they have a type parameter. C++ templates are really just like macros, except they look like classes. <p> The big difference between C# generics and C++ templates shows up in when the type checking occurs and how the instantiation occurs. First of all, C# does the instantiation at runtime. C++ does it at compile time, or perhaps at link time. But regardless, the instantiation happens in C++ before the program runs. That's difference number one. Difference number two is C# does strong type checking when you compile the generic type. For an unconstrained type parameter, like <code>List<T></code>, the only methods available on values of type <code>T</code> are those that are found on type <code>Object</code>, because those are the only methods we can generally guarantee will exist. So in C# generics, we guarantee that any operation you do on a type parameter will succeed. <p> C++ is the opposite. In C++, you can do anything you damn well please on a variable of a type parameter type. But then once you instantiate it, it may not work, and you'll get some cryptic error messages. For example, if you have a type parameter <code>T</code>, and variables <code>x</code> and <code>y</code> of type <code>T</code>, and you say <code>x + y</code>, well you had better have an <code>operator+</code> defined for <code>+</code> of two <code>T</code>s, or you'll get some cryptic error message. So in a sense, C++ templates are actually untyped, or loosely typed. Whereas C# generics are strongly typed." <p> The interview continues on at: <a href="http://www.artima.com/intv/generics3.html">http://www.artima.com/intv/generics3.html</a> <p>BTW, isn't 'latent typing' (or implied typing) a feature from ML and the other functional languages? <p>/ee <hr><b>2004/03/13 03:20 EST (via web):</b><br> "isn't latent typing (or implied typing) a feature from ML" Some statically-checked languages use type inference to derive variable types, so they are said to use implicit-typing in-contrast-to explicit-typing (where the type information is written out in the source code). Similarly interface-types can be explicit (written out in the source code) or implicit. (Note that we can have explicit interfaces in a dynamically-checked language.) Latent typing? Your guess is as good as mine. I see a lot of argument about whether latent typing is good (or would be good for Java), but very little discussion of another of Bruce's points: the kind of "generics" implemented in Java doesn't actually buy you much over just using interfaces; it appears to be primarily designed to hide casting. As long as everything you could do with Java generics could be done with casting and interfaces, what's the point? Even if you don't want latent typing in Java, it is hard to argue that Java generics represent a useful addition to the toolkit. Or maybe I'm missing something? Because I don't see it. adam connor Hmm. My part of that last block started with "I see a lot of argument" -- not sure about the part before that. adam connor <hr><b>2004/03/13 16:27 EST (via web):</b><br> It's really very simple: Java generics are just a way to avoid writing casts. This provides better documentation and gives IDE's and compilers more information to work with for refactoring, code-completion, and error-checking. Some of us think this is useful. Any expectations of additional power are all in your head. C++ template error messages may be long, but it's not that hard to get to the bottom of them. If you actully bother to look at them, rather than giving up and calling them cryptic, there is usually one line that tells you everything you need to know. Well, if there is no semantics bound to interface or to type, then why should we actually _name_ the methods in the interface. If the whole semantics is in the body of the "shoot" method, and not in its signature, why not simply call it "method2365" ? dsg I think bruce would prefer a programming language with a structural rather than nominal type system. Java has long been in the nominal camp. -------------------------------- 2004/03/16 14:47 piglet I think Bruce Eckels misses an important aspect in his discussion. He talks about what might go wrong and states correctly that "it's not possible to prevent people from doing something bad with your programming system no matter how safe you attempt to make it." The missing aspect is clarity and code readability. There is no question that you can make both a Camera and a Gun implement a Shootable interface, whether it makes sense semantically or not. However, this is an explicit design decision. I can look up the definition of Shootable and of all types that depend from it. Bruce may be right that strictly speaking, the type information doesn't include any semantics. If I'm lucky there is some Javadoc telling me what the shoot method is supposed to do and what its parameters mean, but even without this information, the type specification helps a lot to understand the code. If on the other hand, your Shooting class method can take "anything that has a shoot method" as a parameter, it's difficult to understand the design intention. I have no idea what kind of objects this method expects. Somebody else might by chance have designed a class with a shoot method without even knowing about the Shooting class. But that would be impossible to know by reading the code. I therefore get the impression that a single developer might get along very well with latent typing and be grateful for its "enabling" capacity. But as soon as somebody else tries to make sense of that person's code, they would probably prefer direction and clarity. What is true in a natural language, that a word may have different meanings and you need some context to understand an expression, is also true for code. In my understanding, one of the basic ideas of OO is that there are no verbs without nouns. With latent typing, there is still, implicitly, a noun but you miss it. You still operate on an object, but you don't know what it is. In my eyes, this is a step back and hardly justifiable for the sake of "coding convenience". ---------------------------------------------------- A discussion of semantics from the serverside discussion thread: Are semantics what the program does, or what the program indicates it will do? From a dictionary: semantic (adj) : of or relating to the study of meaning and changes of meaning Which brings us to the definition of "meaning": (1) To have in the mind, as a purpose, intention, etc.; to intend; to purpose; to design; as, what do you mean to do? (2) To signify; to indicate; to import; to denote. Do interfaces signfy? Indicate? Import? Denote? I think so. Interfaces, properly used, can signify a lot more than just what method signatures an object supports. They can convey a categorization of purpose, without forcing a particular implementation. I definately see that as as semantics. ------------ 2004/03/16 (Why the hell is there no automatic timestamp? The C++ Shooting example is like overhearing part of a conversation in which people talk about "shooting" and now you wonder whether you should call the police or not because you don't know whether they are going to shoot pictures or people. When I think of it, the English word "shoot" is really only a sequence of letters s h o o t without any semantics. piglet -------------------------------- I disagree with the statement <i>there are no semantics at all "bound to the interface"</i>. Perhaps they are not enforced - but they are there, described in the javadocs. For example the "Serializable" interface doesn't even have any methods. Will. Great article. I diagree with you on one point though. You mention that you can create an interface that will shoot either a gun or a camera by either having Gun and Camera both implement the Shootable interface or by creating a C++ style template. However, there is a difference that you do not mention. If Gun and Camera explicitly implement the Shootable interface then a user of the class knows the author's intent (the author of Gun and Camera that is). In the case of the latent typing, the user of the class does not know the intent of the class's author. In which case I believe the user of the classes may after all shoot himself in the foot. --------------- While I like the bulk of the article, I think Bruce is entirely off-base when talking about the lack of "semantics" in interfaces, toward the end of the article. The interfaces are as tree-roots of a forest that represents how we choose to partition / represent the conceptual (semantic) space within which our program operates. We do our best to hide implementation specifics behind the clean facade of the interface. Ideally, a user of our components need only look at the interfaces and nothing else, and get all the needed semantic information by doing that. Oddly, while Bruce begins by extolling convention/framework-centric enabling mechanisms that require programmer grokking, he turns "huffy" in the end and says that the only semantics enforced with respect to the interfaces are whether the instance has or doesn't have the right signatures. That's the antithesis of his earlier sentiment, which relied in programmer buy-in, respect of the framework, etc. The interfaces are central to expressing semantics cleanly and abstractly. Stan Malyshev ----------
Optional change note
:
For editing help, see
HelpPage
.