4 ms·
How many lines of Java would this take?
- jashkenas 17y agoIn CoffeeScript, it's a few lines less: has_methods: (obj, meth_names) -> name for name in meth_names when obj[name] and obj[name].call
- jerf 17y agoNone. Even with Java's typesystem you can know whether the thing or things you have in your hand implements some interface or not ("callable" in this case) at compile time. You can't ask this question because you can't not already know the answer. I'm not speaking to whether dynamic/duck typing is good or bad here, just pointing out that the question is flawed.
- brehaut 17y agoI believe the question is asking 'if you have an object of unknown type, how do you introspect it to find out if it supports a method with name meth_name'. the test for callability is to determine of the objects member is callable, not if the object itself is callable. Java's reflection system exists to answer this question. I'm not a Java guru though, so i couldnt forumlate the equivalent code
- jerf 17y agoIt is true that my answer elides over some things, but the underlying point is that there isn't a real comparison available between languages because in Java you should pretty much never need this. Yes, technically you could work yourself into a position where you might need that question answered and have to go through the reflection, but that is truly a last resort, whereas in Python it's sort of the first. (I say "sort of" because even in Python this is a weird thing; the traditional answer to the question "can I call this as a function" is to simply try it and catch the exception if it fails.)
- brehaut 17y agowell of course. Its a last resort in python too. while it's much easier to do in python, its far from idiomatic. It's getting into 'too much magic' territory.
- patio11 17y agoYou can't ask this question because you can't not already know the answer. This isn't true. Here's a trivial scenario for you: a user inputs a URL which represents a web service and a method name. Your code needs to determine if the object which will get returned as JSON by that web service implements the method or not. There are more complicated examples which occur in actual production systems. For example, suppose you're interfacing with Big Freaking Enterprise code that you can't change, and there is a rule that certain objects have to have certain checks done prior to being sent over the wire. Those checks might be implemented as methods decorated with @FireThisCheckBeforeSendingThisOverTheWire annotations, but that isn't the only way to skin this particular cat. In particular, your million lines of legacy code might have a coding convention where any method starting with "check" gets fired. This worked fine when the code was only running in its own little world and teams of overpaid engineers maintained lists of all the check methods for various classes, but now that code needs to get exposed via a new API to meet some emergent business need, and you want to accomplish this without touching the million line codebase that nobody really understands. Enter the reflection API. Incidentally, expecting a coding convention like that to actually work isn't totally insane. JUnit 3, I think, treated any method starting with test as a test. I personally prefer it for usability over "slap an annotation on it". Anyhow, Enterprise Java: abandon all hope ye who enter here.
- pvg 17y agoHere's a trivial scenario for you: a user inputs a URL which represents a web service and a method name. Your code needs to determine if the object which will get returned as JSON by that web service implements the method or not. You wouldn't do that by reflection, you'd have a mapping between service method names and objects that perform the service. In fact, this sort of thing is pretty typical in web frameworks based on dynamic languages as well. I don't want you calling Object.notifyAll or whatever just by fiddling with urls. Reflection does come up but it's usually in more magical places - serialization (the built-in serialization is an example of interface-by-convention), profilers, debuggers, prototyping tools.
- ighost 17y agoYou're mistaken. Animal animal = zoo.getAnimal(); Can I do animal.bark() or animal.fly() ? All I know is that it's an Animal of some sort, may or may not be an instance of the Dog or Bird subclasses of Animal.
- pvg 17y agoThis kind of synthetic example is silly, though. The fundamental questions would be the same in Python as well. How did you end up with this heterogeneous collection of objects? Why are you unable to get a collection of objects that are known to support your desired protocol at that point? What happens if they don't? Etc, etc, etc. You might make very different design choices in a statically or dynamically typed language but thinking about zoos and animals with no context isn't particularly informative.
- ighost 17y agoSynthetic? Yes. Contrived? No. I've seen this sort of thing in my own and other people's Java code, where you know what class it is but not the most-derived subclass. That's how polymorphism happens.
- pvg 17y agoRight. It doesn't happen by rooting around objects looking for methods by name. That's usually a sign of some misdesign that's making you re-invent the polymorphic mechanisms of the language yourself. True both in Java and Python.
- ighost 17y agoI agree that polymorphism is the "right way" if there's already a class hierarchy established. If the superclass-subclass relationships aren't in place for you (worse yet, they're not set up how you want them to be set up), this hack accomplishes a similar effect with no refactoring.
- statictype 17y ago
- patio11 17y ago[Disclaimer: I don't read Python, but I think the question here is "Which methods from this list does this object implement?" If I'm wrong please correct me.] My gut check was this should take about eight lines, plus imports and the class boilerplate. Let's try: http://www.pastie.org/808727 http://www.pastie.org/808727 Yep, eight. [Edit: It occurs to me the Python code might answer "Does this implement all specified methods?" That also takes eight lines in Java. I've appended the implementation above.]
- pvg 17y agoYou can take out another couple if you did a sensible thing like taking a Set<String> as input for method names and returned a Set<String> But like the other poster said, you're very unlikely to be doing this in Java, making the whole thing take 0 lines and 129.4 fewer insufferable smugness units.
- brehaut 17y agoThe snippet is imprecise. it should be something like def hasmethod(obj, meth_name): """If it calls like a method it's a method.""" return callable(getattr(obj, meth_name)) if hasattr(obj, meth_name) else False
- ZitchDog 17y agoclass ObjectUtil { static boolean hasMethod(Object obj, String... methodNames) { for(String methodName : methodNames) if(!hasMethod(obj, methodName)) return false; return true; } static boolean hasMethod(Object obj, String methodName) { for(Method method : obj.getClass().getMethods()) if(method.getName().equals(methodName)) return true; return false; } }
- efsavage 17y agoI don't really care how many lines of Java this takes, if someone commits a garbage scenario like this I'm concerned with how many lines of comments they have explaining why they're doing it instead of solving the problem correctly.
- pyman 17y agoIdiots count lines, programmers write them