Nat Pryce wrote: > In Ruby, if I want to load a class Foo::Bar::SomeClass, I have to both > require the file that the class is packaged in, *and* import the module > that > it is defined in. In Java, I just import the module and the class loader > locates the file and loads the class. How classes are organised as files > or other storage media is not exposed in client code. This is picking nits. my.package.and.Class may not have slashes in it, but it is still a filesystem path. And for the record, I almost never import a module to use a class; I do one require, and then access the classes via the Package::Class scheme. This would, of course, become more difficult if we started having long path names, as are common in Java. In any case, your base argument seems to be that you have two disjoint paths to classes in Ruby, and only one in Java, and I agree that this is a valid complaint. > A Java class loader has complete freedom to translate a fully specified > class name (e.g. including the package prefix) into whatever storage > location it wants. The implementation of the system class loader in As I said, you can override "require" in Ruby just as easily (and probably easier) as rewriting the ClassLoader in Java. You can overload require to load classes from over a socket connection. I maintain there isn't any inherant advantage to Java's ClassLoader or the mechanism by which Java resolves class names into objects. > physical storage. If I move a Java class from one JAR file to another, I > don't have > to change any client code. However, if I move a Ruby class definition > from one .rb file to another, I have to change all client code that uses > that class. Therefore Ruby couples client code more tightly to the modules > that it uses than does Java. Ah. I see. I think this is an unfair comparison. How often do you define multiple classes in one source file in Java? Most people do it very rarely. Ruby makes it easier to put multiple classes in a single file, but if you're going to compare the systems, you should use the same basic organizational model. > Yes, you could. That doesn't help reduce the coupling caused by depending > on both the class name *and* the physical storage though. Sure. Consider: def load_class_hash # Find all classes in all .rb files in $: and stick their names into # a hash file. Also query some servers that have archives of Ruby # sources, and get a list of all of the classes they know about. # Stick this hashtable in some global variable, and redefine this method # to do nothing. end def decrypt( name ) name.gsub( /::/, "/" ) end def require( name, auto_import=false ) name = decrypt( name ) load_class_hash() # Now access the hash to find the location of the file that contains # the requested class, and read the stream. Evaluate the stream, # thereby loading that class. For kicks, allow auto-importing: class_def = @@__class__hash__[name].readlines() class_eval class_def class_eval "import #{name}" if auto_import end require "REXML::Document" You can make your class names whatever you want, and you've effectively turned Ruby's "require" into Java's ClassLoader by forcing the paths and names of the require to match the paths and names of the packages and classes. I'm oversimplifying, and you'll probably have some issues with breaking recursive requires that don't use your fancy-pants nameing mechanism, but these issues can be worked around. -- --- SER