Normally, to call a method from its reference, it should go something like below:
$methodref->(#args)
But when invoke a method from its reference returned from "can", it seems inconsistent.
$methodref = $my_obj->can(my_method);
$my_obj->$methodref(#args) if $methodref; # why it isn't $my_obj->$methodref->(#args)?
Can someone please shed some light on this?
Thanks,
CC
The reason is that the object has to be the first thing passed in to the function. This is automatically done for you if you make a method call. But $methodref->($my_obj, #args) will also work.
The CODE ref returned by can doesn’t have an object associated with it once that can is done. That’s why you still need to use an object as an invocant.
Note that this is dangerous, because there is no longer any guarantee that this is method that is supposed to be called on that object. I suppose you might do something like this:
$objmethref = $my_obj->can("methname") && sub { $my_obj->methname(#_) };
# then later
$objmethref->(#args);
but I’m not sure what it is you really want to do.
$my_obj->$methodref->(#args)
is
( $my_obj->$methodref() )->(#args)
In other words, it would call the method with no args, and attempt to use the result as a function reference. It's not what you want at all
The obvious means of calling it is
$methodref->($my_obj, #args)
but Perl provides a syntax that looks like a method-call for your pleasure.
$my_obj->$methodref(#args)
$methodref->(#args) is a function call, not a method call, so won't have the object automatically passed.
$my_obj->$methodref->(#args) would call $methodref with no parameters other than the object parameter, and use its return value as a coderef, calling that and passing it the indicated args.
Related
I just read that the init method can't be used as a value. Meaning:
var x = SomeClass.someClassFunction // ok
var y = SomeClass.init // error
Example found on Language reference
Why should it be like that? Is it a way to enforce language level that too dirty tricks come into place, because of some cohertion or maybe because it interferes with another feature?
Unlike Obj-C, where the init function can be called multiple times without problems, in Swift there actually is no method called init.
init is just a keyword meaning "the following is a constructor". The constructor is called always via MyClass() during the creation of a new instance. It's never called separately as a method myInstance.init(). You can't get a reference to the underlying function because it would be impossible to call it.
This is also connected with the fact that constructors cannot be inherited. Code
var y = SomeClass.init
would also break subtyping because the subtypes are not required to have the same initializers.
Why should it be like that?
init is a special member, not a regular method.
Beyond that, there's no reason that you'd ever need to store init in a variable. The only objects that could use that function in a valid way are instances of the class where that particular init is defined, and any such object will have already been initialized before you could possibly make the assignment.
Initializers don't have a return value. In order to assign it to something, it should be able to return something - and it doesn't.
In netbeans I use to call a method that returns a value, but I am directly calling it where I have to pass a parameter to the function i.e. Function(getValue()) where getValuue() returns String. So what I want to know is that what is more efficient way to call this method whether should I assign value to a string first and then pass that value to parameter, as netbeans suggests me and shows a warning there, or calling it directly is good? I know code runs fine but keeping in mind the efficiency or rules of coding should I consider this thing or not? Or how badly can it effect if I ignore it?
If you are only using that value once, then calling it directly where it is used as a parameter is fine.
In Java, this is fine:
MyClass myClass = new MyClass();
myFunction(myClass.getSomeValue());
Whereas in the following case:
MyClass myClass = new MyClass();
MyOtherClass myOtherClass = myClass.someLongComputation();
Int value = myFunction(myOtherClass);
anotherFunction(value, myOtherClass);
It may be better to have a local variable so that you avoid calling a long running calculation twice. However, for simple getValue()s, it really doesn't matter.
I have a set of methods where I would like the caller to be able to override a value, or it defaults to the instance variable.
So what I keep trying to do is:
method foo( Str :$blah = $self->blah ) {
#doStuff
}
which throws a parsing error so I end up doing this everywhere
method foo( Str :$blah? ) {
$blah = $self->blah unless defined $blah;
#doStuff
}
Not horrendous, but seems silly when MooseX::Method::Signatures supports the default concept and has fixed all my other standard 'start of method' lines.
Invariably when I'm trying to do something like this and I can't find anyone else on the web who's run into the same problems, I'm approaching the problem the wrong way. It seems like I might be trying to jam a functional program into a oo layout, rather than actual oo as the methods are more helper functions for calling externally rather than methods operating on the object. So just checking if I'm just defining it incorrectly or if what I'm doing is "dumb" or just not supported by Parse::Method::Signatures.
AFAIK The Signatures module hooks itself into the Perl parser and injects some code to handle the prototypes. It is remarkable that this works.
That said, using non-constant values as defaults could have issues. And there may be scenarios where calling some code to prepopulate a value could wreak havoc. Specifically, should the code that prepopulates the value should only be called if no value for the argument is given, or should it be always called? What should we do with side effects? What should the caller be? If I have a global $self object, shouldn't that receive the method call, as the scoping rules clearly dictate this? (As our $x=5; my $x=$x; is valid, but just my $x=$x is not). Even better, what would happen if the default value population method call would call the same method, but again without a value for the optional parameter?
You can always fall back to old-school optional parameters:
sub foo {
my ($self, $blah) = #_;
# something like my ($self, $blah) = (#_, $self->blah); wouldn't work, of course.
$blah //= $self->blah; # nicer than old `unless defined`
...;
}
or, in this case:
method foo (:$blah?) {
$blah //= $self->blah
}
I find this use of the defined-or operator quite enjoyable.
For example, there are functions named -(void)Foo, and -(void)Foo:(id)sender.
The -(void)Foo:(id)sender can get the caller from parameter, and my question is, how to get caller from -(void)Foo? Is there any way to get the caller?
Please have a look at Objective C find caller of method. For what do you need it? The (id)sender parameter is passed directly by the method sending the message, there is no magic involved.
I noticed that when you call a superclass's methods, you need to do something like this :
my $self = $class->SUPER::new();
Why isn't that:
my $self = $class->SUPER->new();
I suspect because $class->SUPER->new() would normally be the same as $class->SUPER()->new(). But there isn't a $class->SUPER() function, and its not clear what that would return.
On the other hand, $class->Foo::Bar has always been a valid way to call a method directly by full name, so making a special package-like thing — SUPER — fits in better. (I suspect that you could actually implement SUPER as a package, and maybe it historically was, I don't know)
PS: Take a look at the mro package, and $self->next::method. Also, take a look at Moose if you're going to do serious OO work in Perl.
In short, SUPER isn't a method. It's a virtual package. It's documented in perlobj under the "Method Invocation" section.
Note, however, that SUPER bases itself on the current package, not the package of the instance you used it with.
Method calls have a number of forms:
Calls method, possibly inherited:
->method()
Explicitly calls sub Package::method, whether that's in the inheritance tree or not:
->Package::method()
Explicitly calls the referred-to sub, whether that's in the inheritance tree or not:
->$coderef()
Calls the method that would have been called by __PACKAGE__->method() if there were no sub method in __PACKAGE__ (N.B. the class or object on the left of -> is irrelevant):
->SUPER::method()
Any of the above, depending on the contents of $method:
->$method()
(Legal even under use strict;.)
While the first form is the most common, it's worth learning about the others and how they work.
To add to what derobert said:
You're calling 'new' in the 'SUPER' namespace but passing it the object (or string), '$class'.
You don't have to use SUPER, as you can give the full package name of the parent (useful in cases of diamond inheritance):
sub init {
my $self = shift;
$self->ParentClass1::init();
$self->ParentClass2::init();
}