Method Invocation in Class Definition

Method invocation in class definition?

In Ruby, class declarations are just chunks of code, executed in order.

It's important to remember that inside a class definition, self points to the class itself. validates is a class method of ActiveRecord. As the class is being defined, code in the definition is executed. The validates method resolves to a class method of ActiveRecord, so is called during class definition.

In your Person example, it will only print once, because you only define the class once.

Consider the following:

class Foo
def self.validates_nothing(sym)
(@@syms ||= []) << sym
puts "!!! Here there be logic"
end

def validate
@@syms.each { |s| puts s }
end
end

This defines a class with a class method validates_nothing, and an instance method, validate. validates_nothing just gathers whatever arguments are given it, validate just dumps them out.

class Bar < Foo
validates_nothing :anything
validates_nothing :at_all
end

This defines a subclass. Note that when the class method validates_nothing is called, it prints:

Here there be logic
Here there be logic

If we create a new bar and call validate, we get the expected output:

> Bar.new.validate
!!!anything
!!!at_all

Python calling method in class

The first argument of all methods is usually called self. It refers to the instance for which the method is being called.

Let's say you have:

class A(object):
def foo(self):
print 'Foo'

def bar(self, an_argument):
print 'Bar', an_argument

Then, doing:

a = A()
a.foo() #prints 'Foo'
a.bar('Arg!') #prints 'Bar Arg!'

There's nothing special about this being called self, you could do the following:

class B(object):
def foo(self):
print 'Foo'

def bar(this_object):
this_object.foo()

Then, doing:

b = B()
b.bar() # prints 'Foo'

In your specific case:

dangerous_device = MissileDevice(some_battery)
dangerous_device.move(dangerous_device.RIGHT)

(As suggested in comments MissileDevice.RIGHT could be more appropriate here!)

You could declare all your constants at module level though, so you could do:

dangerous_device.move(RIGHT)

This, however, is going to depend on how you want your code to be organized!

method that gets a class and calls its main function

Given below is how you should define the method:

public static void executeMain(Class<?> cls, Object[] args) {
try {
Object[] param = { args };
Method method = cls.getDeclaredMethod("main", args.getClass());
method.invoke(cls, param);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}

Demo

Assignment1.java:

import java.util.Arrays;

public class Assignment1 {
public static void main(String[] args) {
if (args == null) {
System.out.println("Welcome to Assignment1");
} else {
System.out.println("Arguments to main in Assignment1: " + Arrays.toString(args));
}
}
}

Assignment2.java

import java.util.Arrays;

public class Assignment2 {
public static void main(String[] args) {
if (args == null) {
System.out.println("Welcome to Assignment2");
} else {
System.out.println("Arguments to main in Assignment2: " + Arrays.toString(args));
}
}
}

Test class:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
public static void main(String[] args) {
Assignment1.main(null);
Assignment1.main(new String[] { "Hello", "World" });
Assignment2.main(null);
Assignment2.main(new String[] { "Hello", "World" });
executeMain(Assignment1.class, new String[] { "Good", "Morning" });
executeMain(Assignment2.class, new String[] { "Good", "Morning" });
}

public static void executeMain(Class<?> cls, Object[] args) {
try {
Object[] param = { args };
Method method = cls.getDeclaredMethod("main", args.getClass());
method.invoke(cls, param);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}
}

Output:

Welcome to Assignment1
Arguments to main in Assignment1: [Hello, World]
Welcome to Assignment2
Arguments to main in Assignment2: [Hello, World]
Arguments to main in Assignment1: [Good, Morning]
Arguments to main in Assignment2: [Good, Morning]

Check this to learn more about Java Reflection API.

Method invocation vs method execution

Invoking a method and executing a method are synonyms - they are they same thing.

Perhaps I am misunderstanding your question.

Java language spec: an invocation of Class as return type of method in annotation type

Yes, that's exactly that. The terminology is confusing, rarely used, and I can't seem to find it anywhere in the JSL. It is in a tutorial, though:

To reference the generic Box class from within your code, you must
perform a generic type invocation, which replaces T with some concrete
value, such as Integer:

Box<Integer> integerBox;

You can think of a generic type invocation as being similar to an
ordinary method invocation, but instead of passing an argument to a
method, you are passing a type argument — Integer in this case — to
the Box class itself.

Type Parameter and Type Argument Terminology:
Many developers use the terms "type parameter" and "type argument"
interchangeably, but these terms are not the same. When coding, one
provides type arguments in order to create a parameterized type.
Therefore, the T in Foo<T> is a type parameter and the String in
Foo<String> f is a type argument. This lesson observes this definition
when using these terms.

Like any other variable declaration, this code does not actually
create a new Box object. It simply declares that integerBox will hold
a reference to a "Box of Integer", which is how Box<Integer> is read.

An invocation of a generic type is generally known as a parameterized
type.

The best way to invoke methods in Python class declarations?

Quite simply, the solution is that f does not need to be a member of the class. I am assuming that your thought-process has gone through a Javaish language filter causing the mental block. It goes a little something like this:

def f(n):
return '<' + str(num) + '>'

class C(object):

v = f(9)
w = f(42)

Then when you want to use f again, just use it

>>> f(4)
'<4>'

I think the moral of the tale is "In Python, you don't have to force everything into a class".

Invoking a method of an anonymous class

Can somebody point me to the part of the specification that addresses this?

This will mostly be defined in the section concerning Method invocation expressions:

The first step in processing a method invocation at compile time is to
figure out the name of the method to be invoked and which class or
interface to search for definitions of methods of that name.

For the class or interface to search, there are six cases to consider,
depending on the form that precedes the left parenthesis of the
MethodInvocation:

  • [...]
  • If the form is Primary . [TypeArguments] Identifier, then let T be
    the type of the Primary expression. The class or interface to search
    is T if T is a class or interface type, or the upper bound of T if T
    is a type variable.

Here, the Primary expression is the class instance creation expression. So the type to search is the anonymous type.

Am I right in thinking that the only way you can invoke hello is
immediately like this. What about reflection?

As long as an expression evaluates to the anonymous type T, whether through direct access like you have, or through generics, you have access (regular access rules apply) to the members that T declares. This isn't limited to methods. You can access fields or types, though it's not as useful for types. For example,

Object var = new Object() {
class Nested {
}
}.new Nested();

Since there's no way to refer to the nested type without the enclosing type, you can't declare a variable of that nested type. The usefulness declines very quickly. (Presumably, that's also why you can't have a static nested type within this anonymous class.)

Reflection also exposes this method. The generated anonymous class contains this method, so you can retrieve it and invoke it. The process is the same. The fact that the instance is from an anonymous class doesn't matter. The same strategy as presented in How do I invoke a Java method when given the method name as a string? applies.

For example,

Object ref = new Object() {
public void method() {
System.out.println("hidden");
}
};
Class<?> anonymousClass = ref.getClass();
Method method = anonymousClass.getMethod("method");
method.invoke(ref, new Object[0]);

Don't ever write code like this.

Call Class Method From Another Class

update: Just saw the reference to call_user_func_array in your post. that's different. use getattr to get the function object and then call it with your arguments

class A(object):
def method1(self, a, b, c):
# foo

method = A.method1

method is now an actual function object. that you can call directly (functions are first class objects in python just like in PHP > 5.3) . But the considerations from below still apply. That is, the above example will blow up unless you decorate A.method1 with one of the two decorators discussed below, pass it an instance of A as the first argument or access the method on an instance of A.

a = A()
method = a.method1
method(1, 2)

You have three options for doing this

  1. Use an instance of A to call method1 (using two possible forms)
  2. apply the classmethod decorator to method1: you will no longer be able to reference self in method1 but you will get passed a cls instance in it's place which is A in this case.
  3. apply the staticmethod decorator to method1: you will no longer be able to reference self, or cls in staticmethod1 but you can hardcode references to A into it, though obviously, these references will be inherited by all subclasses of A unless they specifically override method1 and do not call super.

Some examples:

class Test1(object): # always inherit from object in 2.x. it's called new-style classes. look it up
def method1(self, a, b):
return a + b

@staticmethod
def method2(a, b):
return a + b

@classmethod
def method3(cls, a, b):
return cls.method2(a, b)

t = Test1() # same as doing it in another class

Test1.method1(t, 1, 2) #form one of calling a method on an instance
t.method1(1, 2) # form two (the common one) essentially reduces to form one

Test1.method2(1, 2) #the static method can be called with just arguments
t.method2(1, 2) # on an instance or the class

Test1.method3(1, 2) # ditto for the class method. It will have access to the class
t.method3(1, 2) # that it's called on (the subclass if called on a subclass)
# but will not have access to the instance it's called on
# (if it is called on an instance)

Note that in the same way that the name of the self variable is entirely up to you, so is the name of the cls variable but those are the customary values.

Now that you know how to do it, I would seriously think about if you want to do it. Often times, methods that are meant to be called unbound (without an instance) are better left as module level functions in python.



Related Topics



Leave a reply



Submit