

How many lines of Java would this take? - ighost
http://gist.github.com/293947

======
ZitchDog

        class 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;
            }
        }

------
jerf
None. 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.

~~~
ighost
You'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
This 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
Synthetic? 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
Right. 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
I 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.

------
patio11
[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>

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
You 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.

------
efsavage
I 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.

------
brehaut
The 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

~~~
ighost
This function doesn't implement the same functionality. It doesn't even take
the same arguments.

~~~
brehaut
you are quite right. it looks totally different to when i first checked it, so
yes, ignore me.

------
jashkenas
In 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

~~~
rudd
It's actually the same length in Python. Just take out the extra line breaks
from the gist:

    
    
        def hasmethods(obj, *meth_names):
            return all(hasattr(getattr(obj, m, None), '__call__') for m in meth_names)

~~~
ighost
Technically it's one line without semicolons in Python

------
pyman
Idiots count lines, programmers write them

